You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Huge stability push... all (known) paths have been tested heavily on linux with tsan and every single found race condition report has been fixed. Lots of locks have been added/moved/changed and some instances of things have been leaked on purpose to prevent tsan reports during shutdown * More efficient storage proxy implementation which immediately forward segments to clients once they are available in proxy * Added UbaAgent -command=x which can be used to send commands to host. Supported commands are "status"which prints out status of all remote sessions. "abort/abortproxy/abortnonproxy" that can be used to abort remote sessions and "disableremote" to have host stop accepting more helpers * Fixed scheduler::stop bug if remotes were still requesting processes * Added support for process reuse on linux/macos * Added support for Coordinator interface and dynamically load coordinator dll in UbaCli * Restructured code a little bit to be able to queue up all writes in parallel * Added Show create/write colors to visualizer (defaults to on) * Fixed so write file times are visualized in visualizer * Improved socket path for visualizer * Improved a lot of error messages * Fixed double close of memory handle in StorageServer * Changed some ScopedWriteLock to SCOPED_WRITE_LOCK (same for read locks) * Fixed some missing cleanup of trace view when starting a new trace view in visualizer [CL 32137083 by henrik karlsson in ue5-main branch]
208 lines
5.7 KiB
C++
208 lines
5.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include <iostream>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <dlfcn.h>
|
|
|
|
#if PLATFORM_LINUX
|
|
#include <link.h>
|
|
#include <dlfcn.h>
|
|
#else
|
|
#include <mach-o/dyld.h>
|
|
#endif
|
|
|
|
|
|
int LogError(const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
char buffer[1024];
|
|
snprintf(buffer, 1024, format, args);
|
|
printf("%s\n", buffer);
|
|
va_end(args);
|
|
return -1;
|
|
}
|
|
|
|
bool IsLibraryLoaded(const char* libraryToMatch)
|
|
{
|
|
bool foundLib = false;
|
|
#if PLATFORM_LINUX
|
|
// The dl_iterate_phdr() function walks through the list of an
|
|
// application's shared objects and calls the function callback once
|
|
// for each object, until either all shared objects have been
|
|
// processed or callback returns a nonzero value.
|
|
// The last iteration of the callbacks return is propigated all the way up
|
|
foundLib = dl_iterate_phdr([](struct dl_phdr_info* info, size_t size, void* libraryToMatch)
|
|
{
|
|
return strstr(info->dlpi_name, (const char*)libraryToMatch) != 0 ? 1 : 0;
|
|
}, (void*)libraryToMatch);
|
|
#elif PLATFORM_MAC
|
|
|
|
bool foundDetoursLib = false;
|
|
unsigned int count = _dyld_image_count();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
const char* ImageName = _dyld_get_image_name(i);
|
|
if (strstr(ImageName, libraryToMatch))
|
|
{
|
|
foundLib = true;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
return foundLib;
|
|
}
|
|
|
|
|
|
/******************** WARNING ********************/
|
|
// UbaTestAppPosix cannot be run standalone. It is extremely
|
|
// dependent on the UbaTest runner. Please see details in:
|
|
// UbaTestSession.h
|
|
int main(int argc, char* argv[])
|
|
{
|
|
bool runningRemote = false;
|
|
char* tmp = getenv("UBA_REMOTE");
|
|
if (tmp && tmp[0] == '1')
|
|
runningRemote = true;
|
|
|
|
// Make the assumption that if we're running remote the detour lib will be there.
|
|
bool foundDetoursLib = IsLibraryLoaded(UBA_DETOURS_LIBRARY) || runningRemote;
|
|
|
|
|
|
if (!foundDetoursLib)
|
|
return LogError("libUbaDetours not loaded. This app is designed to only start from inside UnrealBuildAccelerator.");
|
|
|
|
if (argc == 1)
|
|
{
|
|
char cwd[1024];
|
|
if (!getcwd(cwd, sizeof(cwd)))
|
|
return LogError("getcwd failed");
|
|
|
|
struct stat attrR;
|
|
if (stat("FileR.h", &attrR) == -1)
|
|
return LogError("stat for FileR.h failed");
|
|
if (S_ISREG(attrR.st_mode) == 0)
|
|
return LogError("stat for FileR.h did not return normal file");
|
|
|
|
int fdr = open("FileR.h", O_RDONLY);
|
|
if (fdr == -1)
|
|
return LogError("open FileR.h failed");
|
|
|
|
char buf[4];
|
|
if (read(fdr, buf, 4) != 4)
|
|
return LogError("Failed to read FileR.h");
|
|
|
|
if (strcmp(buf, "Foo") != 0)
|
|
return LogError("FileR.h content was wrong");
|
|
|
|
if (close(fdr) == -1)
|
|
return LogError("close FileR.h failed");
|
|
|
|
int fdw = open("FileW", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
if (fdw == -1)
|
|
return LogError("open FileW failed");
|
|
|
|
if (write(fdw, "hello", 6) == -1)
|
|
return LogError("write FileW failed");
|
|
|
|
struct stat attrW1;
|
|
if (fstat(fdw, &attrW1) == -1)
|
|
return LogError("fstat FileW failed");
|
|
|
|
if (close(fdw) == -1)
|
|
return LogError("closed FileW failed");
|
|
|
|
struct stat attrW2;
|
|
if (stat("FileW", &attrW2) == -1)
|
|
return LogError("stat for FileW failed");
|
|
if (S_ISREG(attrW2.st_mode) == 0)
|
|
return LogError("stat for FileW did not return normal file");
|
|
|
|
if (rename("FileW", "FileW2") == -1)
|
|
return LogError("rename for FileW to FileW2 failed");
|
|
|
|
|
|
struct stat attrD1;
|
|
if (stat("Dir1", &attrD1) == -1)
|
|
return LogError("stat for FileW failed");
|
|
if (S_ISREG(attrD1.st_mode) != 0)
|
|
return LogError("stat for FileW did not return directory");
|
|
|
|
struct stat attr3;
|
|
if (stat("/usr", &attr3) == -1)
|
|
return LogError("stat for /usr failed");
|
|
|
|
FILE* f = fopen("FileWF", "w+");
|
|
if (f == nullptr)
|
|
return LogError("fopen FileWF failed");
|
|
if (fwrite("Hello", 1, 6, f) != 6)
|
|
return LogError("fwrite FileWF failed");
|
|
if (fclose(f) != 0)
|
|
return LogError("fclose FileWF failed");
|
|
struct stat attrWF;
|
|
if (stat("FileWF", &attrWF) == -1)
|
|
return LogError("stat for FileW failed");
|
|
|
|
#if !PLATFORM_LINUX // Farm linux machines do not have clang installed... need to revisit this
|
|
char fullPath[PATH_MAX];
|
|
if (realpath("/usr/bin/clang", fullPath) == nullptr)
|
|
return LogError("realpath for 'clang' failed");
|
|
#endif
|
|
|
|
struct stat attrRoot;
|
|
if (stat("/", &attrRoot) != 0)
|
|
return LogError("stat for '/' failed");
|
|
return 0;
|
|
}
|
|
else if (strncmp(argv[1], "-file=", 6) == 0)
|
|
{
|
|
void* detoursHandle = dlopen(UBA_DETOURS_LIBRARY, RTLD_LAZY);
|
|
if (!detoursHandle)
|
|
return -3;
|
|
using UbaRequestNextProcessFunc = bool(unsigned int prevExitCode, char* outArguments, unsigned int outArgumentsCapacity);
|
|
static UbaRequestNextProcessFunc* requestNextProcess = (UbaRequestNextProcessFunc*)(void*)dlsym(detoursHandle, "UbaRequestNextProcess");
|
|
if (!requestNextProcess)
|
|
return -8;
|
|
|
|
char arguments[1024];
|
|
const char* file = argv[1] + 6;
|
|
while (true)
|
|
{
|
|
int rh = open(file, O_RDONLY);
|
|
if (rh == -1)
|
|
return LogError("Failed to open file %s", file);
|
|
if (close(rh) == -1)
|
|
return LogError("Failed to close file %s", file);
|
|
|
|
srand(getpid());
|
|
int milliseconds = rand() % 2000;
|
|
struct timespec ts;
|
|
ts.tv_sec = milliseconds / 1000;
|
|
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
|
nanosleep(&ts, NULL);
|
|
|
|
char outFile[1024];
|
|
strcpy(outFile, file);
|
|
outFile[strlen(file)-3] = 0;
|
|
strcat(outFile, ".out");
|
|
|
|
int wh = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
if (wh == -1)
|
|
return LogError("Failed to create file %s", file);
|
|
if (close(wh) == -1)
|
|
return LogError("Failed to close created file %s", file);
|
|
|
|
// Request new process
|
|
if (!requestNextProcess(0, arguments, 1024))
|
|
break; // No process available, exit loop
|
|
file = arguments + 6;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
return -2;
|
|
}
|