From 680934812598d2c9116303f3245e7a9d60ff58bf Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 3 Dec 2013 17:06:06 -0800 Subject: Creating a cleaner branch --- indra/win_crash_logger/CMakeLists.txt | 3 + indra/win_crash_logger/llcrashloggerwindows.cpp | 178 +++++++++++++++++++++++- indra/win_crash_logger/llcrashloggerwindows.h | 34 +++++ indra/win_crash_logger/win_crash_logger.cpp | 40 +++++- 4 files changed, 249 insertions(+), 6 deletions(-) mode change 100755 => 100644 indra/win_crash_logger/llcrashloggerwindows.cpp mode change 100755 => 100644 indra/win_crash_logger/llcrashloggerwindows.h (limited to 'indra/win_crash_logger') diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 3c9a4b9756..c6070020db 100755 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -12,6 +12,7 @@ include(LLWindow) include(LLXML) include(Linking) include(LLSharedLibs) +include(GoogleBreakpad) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -20,6 +21,7 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} + ${BREAKPAD_INCLUDE_DIRECTORIES} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -68,6 +70,7 @@ find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR}) add_executable(windows-crash-logger WIN32 ${win_crash_logger_SOURCE_FILES}) target_link_libraries(windows-crash-logger + ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${LLCRASHLOGGER_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLVFS_LIBRARIES} diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp old mode 100755 new mode 100644 index 36d988ead7..49c7ade135 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -42,6 +42,10 @@ #include "lldxhardware.h" #include "lldir.h" #include "llsdserialize.h" +#include "llsdutil.h" + +#include +#include #define MAX_LOADSTRING 100 #define MAX_STRING 2048 @@ -64,6 +68,7 @@ BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialo std::stringstream gDXInfo; bool gSendLogs = false; +LLCrashLoggerWindows* LLCrashLoggerWindows::sInstance = NULL; //Conversion from char* to wchar* //Replacement for ATL macros, doesn't allocate memory @@ -240,14 +245,181 @@ LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam LLCrashLoggerWindows::LLCrashLoggerWindows(void) { + if (LLCrashLoggerWindows::sInstance==NULL) + { + sInstance = this; + } } LLCrashLoggerWindows::~LLCrashLoggerWindows(void) { + sInstance = NULL; +} + +bool LLCrashLoggerWindows::getMessageWithTimeout(MSG *msg, UINT to) +{ + bool res; + const int timerID=37; + SetTimer(NULL, timerID, to, NULL); + res = GetMessage(msg, NULL, 0, 0); + KillTimer(NULL, timerID); + if (!res) + return false; + if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == 1) + return false; //TIMEOUT! You could call SetLastError() or something... + return true; +} + +int LLCrashLoggerWindows::processingLoop() { + const int millisecs=1000; + static int first_connect = 1; + + LLSD options = getOptionData( LLApp::PRIORITY_COMMAND_LINE ); + + MSG msg; + + bool result; + + while (1) + { + result = getMessageWithTimeout(&msg, millisecs); + if ( result ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (first_connect ) + { + if ( mClientsConnected > 0) + { + first_connect = 0; + } + } + else + { + if (mClientsConnected == 0) + { + break; + } + if (!mKeyMaster.isProcessAlive(mPID, mProcName) ) + { + break; + } + } + } + + llinfos << "session ending.." << llendl; + + llinfos << "clients connected :" << mClientsConnected << llendl; + + return 0; +} + + +void LLCrashLoggerWindows::OnClientConnected(void* context, + const google_breakpad::ClientInfo* client_info) +{ + llinfos << "client start. pid = " << client_info->pid() << llendl; + sInstance->mClientsConnected++; +} + +void LLCrashLoggerWindows::OnClientExited(void* context, + const google_breakpad::ClientInfo* client_info) +{ + llinfos << "client end. pid = " << client_info->pid() << llendl; + sInstance->mClientsConnected--; +} + +/* +void LLCrashLoggerWindows::OnClientDumpRequest(void* context, + const google_breakpad::ClientInfo* client_info, + const std::wstring* file_path) +{ + ProcessingLock lock; + + if (!file_path) + { + llwarns << "dump with no file path" << llendl; + return; + } + if (!client_info) + { + llwarns << "dump with no client info" << llendl; + return; + } + + LLCrashLoggerWindows* self = static_cast(context); + if (!self) + { + llwarns << "dump with no context" << llendl; + return; + } + + DWORD pid = client_info->pid(); + + +// Send the crash dump using a worker thread. This operation has retry +// logic in case there is no internet connection at the time. +DumpJobInfo* dump_job = new DumpJobInfo(pid, self, map, +dump_location.value()); +if (!::QueueUserWorkItem(&CrashService::AsyncSendDump, +dump_job, WT_EXECUTELONGFUNCTION)) { +LOG(ERROR) << "could not queue job"; +} +} +*/ + +bool LLCrashLoggerWindows::initCrashServer() +{ + //For Breakpad on Windows we need a full Out of Process service to get good data. + //This routine starts up the service on a named pipe that the viewer will then + //communicate with. + using namespace google_breakpad; + + LLSD options = getOptionData( LLApp::PRIORITY_COMMAND_LINE ); + std::string dump_path = options["dumpdir"].asString(); + mClientsConnected = 0; + mPID = options["pid"].asInteger(); + mProcName = options["procname"].asString(); + + std::wostringstream ws; + //Generate a quasi-uniq name for the named pipe. For our purposes + //this is unique-enough with least hassle. Worst case for duplicate name + //is a second instance of the viewer will not do crash reporting. + ws << mCrashReportPipeStr << mPID; + std::wstring wpipe_name = ws.str(); + + std::wstring wdump_path; + wdump_path.assign(dump_path.begin(), dump_path.end()); + + //Pipe naming conventions: http://msdn.microsoft.com/en-us/library/aa365783%28v=vs.85%29.aspx + mCrashHandler = new CrashGenerationServer( (WCHAR *)wpipe_name.c_str(), + NULL, + &LLCrashLoggerWindows::OnClientConnected, this, + NULL, NULL, // &LLCrashLoggerWindows::OnClientDumpRequest, this, + &LLCrashLoggerWindows::OnClientExited, this, + NULL, NULL, + true, &wdump_path); + + if (!mCrashHandler) { + //Failed to start the crash server. + llwarns << "Failed to init crash server." << llendl; + return false; + } + + // Start servicing clients. + if (!mCrashHandler->Start()) { + llwarns << "Failed to start crash server." << llendl; + return false; + } + + return true; } bool LLCrashLoggerWindows::init(void) { + initCrashServer(); bool ok = LLCrashLogger::init(); if(!ok) return false; @@ -291,18 +463,16 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles() SetCursor(gCursorWait); // At this point we're responsive enough the user could click the close button SetCursor(gCursorArrow); - mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); + //mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized. } bool LLCrashLoggerWindows::mainLoop() { llinfos << "CrashSubmitBehavior is " << mCrashBehavior << llendl; - // Note: parent hwnd is 0 (the desktop). No dlg proc. See Petzold (5th ed) HexCalc example, Chapter 11, p529 // win_crash_logger.rc has been edited by hand. // Dialogs defined with CLASS "WIN_CRASH_LOGGER" (must be same as szWindowClass) gProductName = mProductName; - gHwndProgress = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROGRESS), 0, NULL); ProcessCaption(gHwndProgress); ShowWindow(gHwndProgress, SW_HIDE ); @@ -371,5 +541,7 @@ bool LLCrashLoggerWindows::cleanup() } PostQuitMessage(0); commonCleanup(); + mKeyMaster.releaseMaster(); return true; } + diff --git a/indra/win_crash_logger/llcrashloggerwindows.h b/indra/win_crash_logger/llcrashloggerwindows.h old mode 100755 new mode 100644 index 5c45a998b3..85cafd54c8 --- a/indra/win_crash_logger/llcrashloggerwindows.h +++ b/indra/win_crash_logger/llcrashloggerwindows.h @@ -31,20 +31,54 @@ #include "windows.h" #include "llstring.h" +class LLSD; + +namespace google_breakpad { + class CrashGenerationServer; + class ClientInfo; +} + class LLCrashLoggerWindows : public LLCrashLogger { public: LLCrashLoggerWindows(void); ~LLCrashLoggerWindows(void); + static LLCrashLoggerWindows* sInstance; + virtual bool init(); virtual bool mainLoop(); virtual void updateApplication(const std::string& message = LLStringUtil::null); virtual bool cleanup(); virtual void gatherPlatformSpecificFiles(); void setHandle(HINSTANCE hInst) { mhInst = hInst; } + int clients_connected() const { + return mClientsConnected; + } + bool getMessageWithTimeout(MSG *msg, UINT to); + + // Starts the processing loop. This function does not return unless the + // user is logging off or the user closes the crash service window. The + // return value is a good number to pass in ExitProcess(). + int processingLoop(); private: void ProcessDlgItemText(HWND hWnd, int nIDDlgItem); void ProcessCaption(HWND hWnd); + bool initCrashServer(); + google_breakpad::CrashGenerationServer* mCrashHandler; + static void OnClientConnected(void* context, + const google_breakpad::ClientInfo* client_info); + + /*static void OnClientDumpRequest( + void* context, + const google_breakpad::ClientInfo* client_info, + const std::wstring* file_path);*/ + + static void OnClientExited(void* context, + const google_breakpad::ClientInfo* client_info); + int mClientsConnected; + int mPID; + std::string mProcName; + HINSTANCE mhInst; }; diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp index 8e916ae437..ede81a406e 100755 --- a/indra/win_crash_logger/win_crash_logger.cpp +++ b/indra/win_crash_logger/win_crash_logger.cpp @@ -28,6 +28,34 @@ #include "stdafx.h" #include #include "llcrashloggerwindows.h" +#include + +//SPATTERS killme +#include +#include + +std::ofstream gCLOG; //SPATTERS for testing only remove ASAP. + +void flog (std::string msg) +{ + //Windows can't even write a goddamned file without fucking it up. + static bool first_time=true; + + std::cout << "Init Crash Logger" << std::endl; + static std::string logname="C:\\Users\\Aura\\AppData\\Roaming\\SecondLife\\logs\\WinCrashLog.log"; + if (first_time) + { + gCLOG.open(logname, std::fstream::out); //first time open for overwrite. + first_time = false; + gCLOG << "BEGINNING Windows Crash Report Log\n"; + } + else + gCLOG.open(logname, std::fstream::out | std::fstream::app); + + gCLOG << msg << "\n"; + gCLOG.close(); +} +//END SPATTERS KILLME int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, @@ -35,17 +63,23 @@ int APIENTRY WinMain(HINSTANCE hInstance, int nCmdShow) { llinfos << "Starting crash reporter." << llendl; - LLCrashLoggerWindows app; app.setHandle(hInstance); app.parseCommandOptions(__argc, __argv); + LLSD options = LLApp::instance()->getOptionData( + LLApp::PRIORITY_COMMAND_LINE); + if (!(options.has("pid") && options.has("dumpdir"))) + { + llwarns << "Insufficient parameters to crash report." << llendl; + } if (! app.init()) { llwarns << "Unable to initialize application." << llendl; - return -1; + return 1; } - + flog("Hi there."); + app.processingLoop(); app.mainLoop(); app.cleanup(); llinfos << "Crash reporter finished normally." << llendl; -- cgit v1.2.3