/** * Generates information for crash reporter */ void GenerateCrashInfoAndLaunchReporter(const FLinuxCrashContext & Context) { // do not report crashes for tools (particularly for crash reporter itself) #if !IS_PROGRAM // create a crash-specific directory FString CrashInfoFolder = FString::Printf(TEXT("crashinfo-%s-pid-%d"), FApp::GetGameName(), getpid()); FString CrashInfoAbsolute = FPaths::ConvertRelativePathToFull(CrashInfoFolder); if (IFileManager::Get().MakeDirectory(*CrashInfoFolder)) { // generate "minidump" Context.GenerateReport(FPaths::Combine(*CrashInfoFolder, TEXT("diagnostics.txt"))); // generate "WER" GenerateWindowsErrorReport(FPaths::Combine(*CrashInfoFolder, TEXT("wermeta.xml"))); // generate "minidump" (just >1 byte) GenerateMinidump(FPaths::Combine(*CrashInfoFolder, TEXT("minidump.dmp"))); // copy log FString LogSrcAbsolute = FPlatformOutputDevices::GetAbsoluteLogFilename(); FString LogDstAbsolute = FPaths::Combine(*CrashInfoAbsolute, *FPaths::GetCleanFilename(LogSrcAbsolute)); FPaths::NormalizeDirectoryName(LogDstAbsolute); static_cast<void>(IFileManager::Get().Copy(*LogDstAbsolute, *LogSrcAbsolute)); // best effort, so don't care about result: couldn't copy -> tough, no log // try launching the tool and wait for its exit, if at all const TCHAR * RelativePathToCrashReporter = TEXT("../../../engine/binaries/linux/crashreportclient"); // FIXME: painfully hard-coded FProcHandle RunningProc = FPlatformProcess::CreateProc(RelativePathToCrashReporter, *(CrashInfoAbsolute + TEXT("/")), true, false, false, NULL, 0, NULL, NULL); if (FPlatformProcess::IsProcRunning(RunningProc)) { // do not wait indefinitely double kTimeOut = 3 * 60.0; double StartSeconds = FPlatformTime::Seconds(); for(;;) { if (!FPlatformProcess::IsProcRunning(RunningProc)) { break; } if (FPlatformTime::Seconds() - StartSeconds > kTimeOut) { break; } }; } } #endif FPlatformMisc::RequestExit(true); }
/** * Generates information for crash reporter */ void DLLEXPORT GenerateCrashInfoAndLaunchReporter(const FLinuxCrashContext & Context) { // do not report crashes for tools (particularly for crash reporter itself) #if !IS_PROGRAM // create a crash-specific directory FString CrashInfoFolder = FString::Printf(TEXT("crashinfo-%s-pid-%d-%s-%s"), FApp::GetGameName(), getpid(), *FDateTime::Now().ToString(), *FGuid::NewGuid().ToString()); FString CrashInfoAbsolute = FPaths::ConvertRelativePathToFull(CrashInfoFolder); if (IFileManager::Get().MakeDirectory(*CrashInfoFolder)) { // generate "minidump" Context.GenerateReport(FPaths::Combine(*CrashInfoFolder, TEXT("diagnostics.txt"))); // generate "WER" GenerateWindowsErrorReport(FPaths::Combine(*CrashInfoFolder, TEXT("wermeta.xml"))); // generate "minidump" (just >1 byte) GenerateMinidump(FPaths::Combine(*CrashInfoFolder, TEXT("minidump.dmp"))); // Introduces a new runtime crash context. Will replace all Windows related crash reporting. //FCStringAnsi::Strncpy(FilePath, CrashInfoFolder, PATH_MAX); //FCStringAnsi::Strcat(FilePath, PATH_MAX, "/" ); //FCStringAnsi::Strcat(FilePath, PATH_MAX, FGenericCrashContext::CrashContextRuntimeXMLNameA ); //SerializeAsXML( FilePath ); @todo uncomment after verification // copy log FString LogSrcAbsolute = FPlatformOutputDevices::GetAbsoluteLogFilename(); FString LogDstAbsolute = FPaths::Combine(*CrashInfoAbsolute, *FPaths::GetCleanFilename(LogSrcAbsolute)); FPaths::NormalizeDirectoryName(LogDstAbsolute); static_cast<void>(IFileManager::Get().Copy(*LogDstAbsolute, *LogSrcAbsolute)); // best effort, so don't care about result: couldn't copy -> tough, no log // try launching the tool and wait for its exit, if at all const TCHAR * RelativePathToCrashReporter = TEXT("../../../Engine/Binaries/Linux/CrashReportClient"); // FIXME: painfully hard-coded if (!FPaths::FileExists(RelativePathToCrashReporter)) { RelativePathToCrashReporter = TEXT("../../../engine/binaries/linux/crashreportclient"); // FIXME: even more painfully hard-coded } // show on the console printf("Starting %s\n", StringCast<ANSICHAR>(RelativePathToCrashReporter).Get()); FProcHandle RunningProc = FPlatformProcess::CreateProc(RelativePathToCrashReporter, *(CrashInfoAbsolute + TEXT("/")), true, false, false, NULL, 0, NULL, NULL); if (FPlatformProcess::IsProcRunning(RunningProc)) { // do not wait indefinitely double kTimeOut = 3 * 60.0; double StartSeconds = FPlatformTime::Seconds(); for(;;) { if (!FPlatformProcess::IsProcRunning(RunningProc)) { break; } if (FPlatformTime::Seconds() - StartSeconds > kTimeOut) { break; } FPlatformProcess::Sleep(1.0f); }; } } #endif FPlatformMisc::RequestExit(true); }