summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewerwin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewerwin32.cpp')
-rw-r--r--indra/newview/llappviewerwin32.cpp228
1 files changed, 107 insertions, 121 deletions
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index d208e135bb..25d18fa11f 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -139,6 +139,9 @@ namespace
{
// user name, when we have it
sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname()));
+
+ sBugSplatSender->sendAdditionalFile(
+ WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "settings_per_account.xml")));
}
// LL_ERRS message, when there is one
@@ -174,7 +177,7 @@ static void exceptionTerminateHandler()
long *null_ptr;
null_ptr = 0;
*null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
- //LLAppViewer::handleViewerCrash();
+
// we've probably been killed-off before now, but...
gOldTerminateHandler(); // call old terminate() handler
}
@@ -362,10 +365,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
-#if LL_SEND_CRASH_REPORTS
- // ::SetUnhandledExceptionFilter(catchallCrashHandler);
-#endif
-
// Set a debug info flag to indicate if multiple instances are running.
bool found_other_instance = !create_app_mutex();
gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance);
@@ -500,68 +499,76 @@ void LLAppViewerWin32::disableWinErrorReporting()
}
const S32 MAX_CONSOLE_LINES = 500;
+// Only defined in newer SDKs than we currently use
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 4
+#endif
-static bool create_console()
-{
- int h_con_handle;
- long l_std_handle;
-
- CONSOLE_SCREEN_BUFFER_INFO coninfo;
- FILE *fp;
-
- // allocate a console for this app
- const bool isConsoleAllocated = AllocConsole();
-
- // set the screen buffer to be big enough to let us scroll text
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
- coninfo.dwSize.Y = MAX_CONSOLE_LINES;
- SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
+namespace {
- // redirect unbuffered STDOUT to the console
- l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
- h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- if (h_con_handle == -1)
- {
- LL_WARNS() << "create_console() failed to open stdout handle" << LL_ENDL;
- }
- else
- {
- fp = _fdopen( h_con_handle, "w" );
- *stdout = *fp;
- setvbuf( stdout, NULL, _IONBF, 0 );
- }
+void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode="w");
- // redirect unbuffered STDIN to the console
- l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE);
- h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- if (h_con_handle == -1)
- {
- LL_WARNS() << "create_console() failed to open stdin handle" << LL_ENDL;
- }
- else
- {
- fp = _fdopen( h_con_handle, "r" );
- *stdin = *fp;
- setvbuf( stdin, NULL, _IONBF, 0 );
- }
+bool create_console()
+{
+ // allocate a console for this app
+ const bool isConsoleAllocated = AllocConsole();
- // redirect unbuffered STDERR to the console
- l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE);
- h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- if (h_con_handle == -1)
- {
- LL_WARNS() << "create_console() failed to open stderr handle" << LL_ENDL;
- }
- else
- {
- fp = _fdopen( h_con_handle, "w" );
- *stderr = *fp;
- setvbuf( stderr, NULL, _IONBF, 0 );
- }
+ if (isConsoleAllocated)
+ {
+ // set the screen buffer to be big enough to let us scroll text
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
+ coninfo.dwSize.Y = MAX_CONSOLE_LINES;
+ SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
+
+ // redirect unbuffered STDOUT to the console
+ set_stream("stdout", stdout, STD_OUTPUT_HANDLE, "CONOUT$");
+ // redirect unbuffered STDERR to the console
+ set_stream("stderr", stderr, STD_ERROR_HANDLE, "CONOUT$");
+ // redirect unbuffered STDIN to the console
+ // Don't bother: our console is solely for log output. We never read stdin.
+// set_stream("stdin", stdin, STD_INPUT_HANDLE, "CONIN$", "r");
+ }
return isConsoleAllocated;
}
+void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode)
+{
+ // SL-13528: This code used to be based on
+ // http://dslweb.nwnexus.com/~ast/dload/guicon.htm
+ // (referenced in https://stackoverflow.com/a/191880).
+ // But one of the comments on that StackOverflow answer points out that
+ // assigning to *stdout or *stderr "probably doesn't even work with the
+ // Universal CRT that was introduced in 2015," suggesting freopen_s()
+ // instead. Code below is based on https://stackoverflow.com/a/55875595.
+ auto std_handle = GetStdHandle(handle_id);
+ if (std_handle == INVALID_HANDLE_VALUE)
+ {
+ LL_WARNS() << "create_console() failed to get " << desc << " handle" << LL_ENDL;
+ }
+ else
+ {
+ if (mode == std::string("w"))
+ {
+ // Enable color processing on Windows 10 console windows.
+ DWORD dwMode = 0;
+ GetConsoleMode(std_handle, &dwMode);
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ SetConsoleMode(std_handle, dwMode);
+ }
+ // Redirect the passed fp to the console.
+ FILE* ignore;
+ if (freopen_s(&ignore, name, mode, fp) == 0)
+ {
+ // use unbuffered I/O
+ setvbuf( fp, NULL, _IONBF, 0 );
+ }
+ }
+}
+
+} // anonymous namespace
+
LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
mCmdLine(cmd_line),
mIsConsoleAllocated(false)
@@ -592,12 +599,16 @@ bool LLAppViewerWin32::init()
#if ! defined(LL_BUGSPLAT)
#pragma message("Building without BugSplat")
- LLAppViewer* pApp = LLAppViewer::instance();
- pApp->initCrashReporting();
-
#else // LL_BUGSPLAT
#pragma message("Building with BugSplat")
+ if (!isSecondInstance())
+ {
+ // Cleanup previous session
+ std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
+ LLFile::remove(log_file, ENOENT);
+ }
+
std::string build_data_fname(
gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE
@@ -605,7 +616,7 @@ bool LLAppViewerWin32::init()
llifstream inf(build_data_fname.c_str());
if (! inf.is_open())
{
- LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname
+ LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname
<< "'" << LL_ENDL;
}
else
@@ -615,7 +626,7 @@ bool LLAppViewerWin32::init()
if (! reader.parse(inf, build_data, false)) // don't collect comments
{
// gah, the typo is baked into Json::Reader API
- LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname
+ LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname
<< "': " << reader.getFormatedErrorMessages() << LL_ENDL;
}
else
@@ -623,7 +634,7 @@ bool LLAppViewerWin32::init()
Json::Value BugSplat_DB = build_data["BugSplat DB"];
if (! BugSplat_DB)
{
- LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
+ LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
<< build_data_fname << "'" << LL_ENDL;
}
else
@@ -634,18 +645,35 @@ bool LLAppViewerWin32::init()
LL_VIEWER_VERSION_PATCH << '.' <<
LL_VIEWER_VERSION_BUILD));
+ DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting
+ MDSF_PREVENTHIJACKING; // disallow swiping Exception filter
+
+ bool needs_log_file = !isSecondInstance() && debugLoggingEnabled("BUGSPLAT");
+ if (needs_log_file)
+ {
+ // Startup only!
+ LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL;
+ dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE;
+ }
+
// have to convert normal wide strings to strings of __wchar_t
sBugSplatSender = new MiniDmpSender(
WCSTR(BugSplat_DB.asString()),
WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)),
WCSTR(version_string),
nullptr, // szAppIdentifier -- set later
- MDSF_NONINTERACTIVE | // automatically submit report without prompting
- MDSF_PREVENTHIJACKING); // disallow swiping Exception filter
+ dwFlags);
sBugSplatSender->setCallback(bugsplatSendLog);
+ if (needs_log_file)
+ {
+ // Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash
+ std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
+ sBugSplatSender->setLogFilePath(WCSTR(log_file));
+ }
+
// engage stringize() overload that converts from wstring
- LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
+ LL_INFOS("BUGSPLAT") << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
<< ' ' << stringize(version_string) << ')' << LL_ENDL;
} // got BugSplat_DB
} // parsed build_data.json
@@ -674,6 +702,16 @@ bool LLAppViewerWin32::cleanup()
return result;
}
+void LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
+{
+#if defined(LL_BUGSPLAT)
+ if (sBugSplatSender)
+ {
+ sBugSplatSender->createReport((EXCEPTION_POINTERS*)pExcepInfo);
+ }
+#endif // LL_BUGSPLAT
+}
+
void LLAppViewerWin32::initLoggingAndGetLastDuration()
{
LLAppViewer::initLoggingAndGetLastDuration();
@@ -802,59 +840,7 @@ bool LLAppViewerWin32::beingDebugged()
bool LLAppViewerWin32::restoreErrorTrap()
{
- return true;
- //return LLWinDebug::checkExceptionHandler();
-}
-
-void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
-{
- if (isSecondInstance()) return; //BUG-5707 do not start another crash reporter for second instance.
-
- const char* logger_name = "win_crash_logger.exe";
- std::string exe_path = gDirUtilp->getExecutableDir();
- exe_path += gDirUtilp->getDirDelimiter();
- exe_path += logger_name;
-
- std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
- std::string appname = gDirUtilp->getExecutableFilename();
-
- S32 slen = logdir.length() -1;
- S32 end = slen;
- while (logdir.at(end) == '/' || logdir.at(end) == '\\') end--;
-
- if (slen !=end)
- {
- logdir = logdir.substr(0,end+1);
- }
- //std::string arg_str = "\"" + exe_path + "\" -dumpdir \"" + logdir + "\" -procname \"" + appname + "\" -pid " + stringize(LLApp::getPid());
- //_spawnl(_P_NOWAIT, exe_path.c_str(), arg_str.c_str(), NULL);
- std::string arg_str = "\"" + exe_path + "\" -dumpdir \"" + logdir + "\" -procname \"" + appname + "\" -pid " + stringize(LLApp::getPid());
-
- STARTUPINFO startInfo={sizeof(startInfo)};
- PROCESS_INFORMATION processInfo;
-
- std::wstring exe_wstr;
- exe_wstr = utf8str_to_utf16str(exe_path);
-
- std::wstring arg_wstr;
- arg_wstr = utf8str_to_utf16str(arg_str);
-
- LL_INFOS("CrashReport") << "Creating crash reporter process " << exe_path << " with params: " << arg_str << LL_ENDL;
- if(CreateProcess(exe_wstr.c_str(),
- &arg_wstr[0], // Application arguments
- 0,
- 0,
- FALSE,
- CREATE_DEFAULT_ERROR_MODE,
- 0,
- 0, // Working directory
- &startInfo,
- &processInfo) == FALSE)
- // Could not start application -> call 'GetLastError()'
- {
- LL_WARNS("CrashReport") << "CreateProcess failed " << GetLastError() << LL_ENDL;
- return;
- }
+ return true; // we don't check for handler collisions on windows, so just say they're ok
}
//virtual