summaryrefslogtreecommitdiff
path: root/indra/win_crash_logger
diff options
context:
space:
mode:
Diffstat (limited to 'indra/win_crash_logger')
-rwxr-xr-xindra/win_crash_logger/CMakeLists.txt3
-rw-r--r--[-rwxr-xr-x]indra/win_crash_logger/llcrashloggerwindows.cpp178
-rw-r--r--[-rwxr-xr-x]indra/win_crash_logger/llcrashloggerwindows.h34
-rwxr-xr-xindra/win_crash_logger/win_crash_logger.cpp40
4 files changed, 249 insertions, 6 deletions
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
index 36d988ead7..49c7ade135 100755..100644
--- 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 <client/windows/crash_generation/crash_generation_server.h>
+#include <client/windows/crash_generation/client_info.h>
#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<LLCrashLoggerWindows*>(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
index 5c45a998b3..85cafd54c8 100755..100644
--- 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 <stdlib.h>
#include "llcrashloggerwindows.h"
+#include <iostream>
+
+//SPATTERS killme
+#include <iostream>
+#include <fstream>
+
+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;