diff options
Diffstat (limited to 'indra/newview/llappviewerwin32.cpp')
-rw-r--r-- | indra/newview/llappviewerwin32.cpp | 355 |
1 files changed, 292 insertions, 63 deletions
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index d328567a0e..57fb84bbf1 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -26,17 +26,16 @@ #include "llviewerprecompiledheaders.h" -#if defined(_DEBUG) -# if _MSC_VER >= 1400 // Visual C++ 2005 or later -# define WINDOWS_CRT_MEM_CHECKS 1 -# endif +#ifdef INCLUDE_VLD +#include "vld.h" #endif +#include "llwin32headers.h" -#include "llappviewerwin32.h" +#include "llwindowwin32.h" // *FIX: for setting gIconResource. -#include "llmemtype.h" +#include "llappviewerwin32.h" -#include "llwindowwin32.cpp" // *FIX: for setting gIconResource. +#include "llgl.h" #include "res/resource.h" // *FIX: for setting gIconResource. #include <fcntl.h> //_O_APPEND @@ -48,8 +47,12 @@ #include "llviewercontrol.h" #include "lldxhardware.h" +#include "nvapi/nvapi.h" +#include "nvapi/NvApiDriverSettings.h" + +#include <stdlib.h> + #include "llweb.h" -#include "llsecondlifeurls.h" #include "llviewernetwork.h" #include "llmd5.h" @@ -62,6 +65,34 @@ #include "llwindebug.h" #endif +#include "stringize.h" + +#include <exception> +namespace +{ + void (*gOldTerminateHandler)() = NULL; +} + +static void exceptionTerminateHandler() +{ + // reinstall default terminate() handler in case we re-terminate. + if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler); + // treat this like a regular viewer crash, with nice stacktrace etc. + 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 +} + +LONG WINAPI catchallCrashHandler(EXCEPTION_POINTERS * /*ExceptionInfo*/) +{ + LL_WARNS() << "Hit last ditch-effort attempt to catch crash." << LL_ENDL; + exceptionTerminateHandler(); + return 0; +} + // *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib // The lib was compiled under VS2005 - in VS2003 we need to remap assert #ifdef LL_DEBUG @@ -69,7 +100,7 @@ extern "C" { void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) { - llerrs << _Message << llendl; + LL_ERRS() << _Message << LL_ENDL; } } #endif @@ -77,6 +108,20 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; +/* + This function is used to print to the command line a text message + describing the nvapi error and quits +*/ +void nvapi_error(NvAPI_Status status) +{ + NvAPI_ShortString szDesc = {0}; + NvAPI_GetErrorMessage(status, szDesc); + LL_WARNS() << szDesc << LL_ENDL; + + //should always trigger when asserts are enabled + //llassert(status == NVAPI_OK); +} + // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -98,6 +143,78 @@ bool create_app_mutex() return result; } +void ll_nvapi_init(NvDRSSessionHandle hSession) +{ + // (2) load all the system settings into the session + NvAPI_Status status = NvAPI_DRS_LoadSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + NvAPI_UnicodeString profile_name; + std::string app_name = LLTrans::getString("APP_NAME"); + llutf16string w_app_name = utf8str_to_utf16str(app_name); + wsprintf(profile_name, L"%s", w_app_name.c_str()); + status = NvAPI_DRS_SetCurrentGlobalProfile(hSession, profile_name); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + // (3) Obtain the current profile. + NvDRSProfileHandle hProfile = 0; + status = NvAPI_DRS_GetCurrentGlobalProfile(hSession, &hProfile); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + // load settings for querying + status = NvAPI_DRS_LoadSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + //get the preferred power management mode for Second Life + NVDRS_SETTING drsSetting = {0}; + drsSetting.version = NVDRS_SETTING_VER; + status = NvAPI_DRS_GetSetting(hSession, hProfile, PREFERRED_PSTATE_ID, &drsSetting); + if (status == NVAPI_SETTING_NOT_FOUND) + { //only override if the user hasn't specifically set this setting + // (4) Specify that we want the VSYNC disabled setting + // first we fill the NVDRS_SETTING struct, then we call the function + drsSetting.version = NVDRS_SETTING_VER; + drsSetting.settingId = PREFERRED_PSTATE_ID; + drsSetting.settingType = NVDRS_DWORD_TYPE; + drsSetting.u32CurrentValue = PREFERRED_PSTATE_PREFER_MAX; + status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + // (5) Now we apply (or save) our changes to the system + status = NvAPI_DRS_SaveSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + } + else if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } +} + //#define DEBUGGING_SEH_FILTER 1 #if DEBUGGING_SEH_FILTER # define WINMAIN DebuggingWinMain @@ -110,19 +227,21 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow) { - LLMemType mt1(LLMemType::MTYPE_STARTUP); - const S32 MAX_HEAPS = 255; DWORD heap_enable_lfh_error[MAX_HEAPS]; S32 num_heaps = 0; #if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit -#elif 1 +#elif 0 // Experimental - enable the low fragmentation heap // This results in a 2-3x improvement in opening a new Inventory window (which uses a large numebr of allocations) // Note: This won't work when running from the debugger unless the _NO_DEBUG_HEAP environment variable is set to 1 + // Enable to get mem debugging within visual studio. +#if LL_DEBUG + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#else _CrtSetDbgFlag(0); // default, just making explicit ULONG ulEnableLFH = 2; @@ -137,14 +256,21 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, heap_enable_lfh_error[i] = GetLastError(); } #endif +#endif // *FIX: global gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); + gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); + 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); @@ -152,19 +278,40 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, bool ok = viewer_app_ptr->init(); if(!ok) { - llwarns << "Application init failed." << llendl; + LL_WARNS() << "Application init failed." << LL_ENDL; return -1; } + NvAPI_Status status; + + // Initialize NVAPI + status = NvAPI_Initialize(); + NvDRSSessionHandle hSession = 0; + + if (status == NVAPI_OK) + { + // Create the session handle to access driver settings + status = NvAPI_DRS_CreateSession(&hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + } + else + { + //override driver setting as needed + ll_nvapi_init(hSession); + } + } + // Have to wait until after logging is initialized to display LFH info if (num_heaps > 0) { - llinfos << "Attempted to enable LFH for " << num_heaps << " heaps." << llendl; + LL_INFOS() << "Attempted to enable LFH for " << num_heaps << " heaps." << LL_ENDL; for(S32 i = 0; i < num_heaps; i++) { if (heap_enable_lfh_error[i]) { - llinfos << " Failed to enable LFH for heap: " << i << " Error: " << heap_enable_lfh_error[i] << llendl; + LL_INFOS() << " Failed to enable LFH for heap: " << i << " Error: " << heap_enable_lfh_error[i] << LL_ENDL; } } } @@ -183,14 +330,14 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, // app cleanup if there was a problem. // #if WINDOWS_CRT_MEM_CHECKS - llinfos << "CRT Checking memory:" << llendflush; + LL_INFOS() << "CRT Checking memory:" << LL_ENDL; if (!_CrtCheckMemory()) { - llwarns << "_CrtCheckMemory() failed at prior to cleanup!" << llendflush; + LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL; } else { - llinfos << " No corruption detected." << llendflush; + LL_INFOS() << " No corruption detected." << LL_ENDL; } #endif @@ -199,14 +346,14 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, viewer_app_ptr->cleanup(); #if WINDOWS_CRT_MEM_CHECKS - llinfos << "CRT Checking memory:" << llendflush; + LL_INFOS() << "CRT Checking memory:" << LL_ENDL; if (!_CrtCheckMemory()) { - llwarns << "_CrtCheckMemory() failed after cleanup!" << llendflush; + LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL; } else { - llinfos << " No corruption detected." << llendflush; + LL_INFOS() << " No corruption detected." << LL_ENDL; } #endif @@ -223,6 +370,15 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LLAppViewer::sUpdaterInfo = NULL ; } + + + // (NVAPI) (6) We clean up. This is analogous to doing a free() + if (hSession) + { + NvAPI_DRS_DestroySession(hSession); + hSession = 0; + } + return 0; } @@ -268,11 +424,11 @@ void LLAppViewerWin32::disableWinErrorReporting() if( 0 == pAddERExcludedApplicationA( executable_name ) ) { U32 error_code = GetLastError(); - llinfos << "AddERExcludedApplication() failed with error code " << error_code << llendl; + LL_INFOS() << "AddERExcludedApplication() failed with error code " << error_code << LL_ENDL; } else { - llinfos << "AddERExcludedApplication() success for " << executable_name << llendl; + LL_INFOS() << "AddERExcludedApplication() success for " << executable_name << LL_ENDL; } } FreeLibrary( fault_rep_dll_handle ); @@ -282,7 +438,7 @@ void LLAppViewerWin32::disableWinErrorReporting() const S32 MAX_CONSOLE_LINES = 500; -void create_console() +static bool create_console() { int h_con_handle; long l_std_handle; @@ -291,7 +447,7 @@ void create_console() FILE *fp; // allocate a console for this app - AllocConsole(); + const bool isConsoleAllocated = AllocConsole(); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); @@ -301,27 +457,51 @@ void create_console() // redirect unbuffered STDOUT to the console l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE); h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - fp = _fdopen( h_con_handle, "w" ); - *stdout = *fp; - setvbuf( stdout, NULL, _IONBF, 0 ); + 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 ); + } // redirect unbuffered STDIN to the console l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE); h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - fp = _fdopen( h_con_handle, "r" ); - *stdin = *fp; - setvbuf( stdin, NULL, _IONBF, 0 ); + 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 ); + } // redirect unbuffered STDERR to the console l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE); h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - fp = _fdopen( h_con_handle, "w" ); - *stderr = *fp; - setvbuf( stderr, NULL, _IONBF, 0 ); + 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 ); + } + + return isConsoleAllocated; } LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) : - mCmdLine(cmd_line) + mCmdLine(cmd_line), + mIsConsoleAllocated(false) { } @@ -337,14 +517,26 @@ bool LLAppViewerWin32::init() // (Don't send our data to Microsoft--at least until we are Logo approved and have a way // of getting the data back from them.) // - llinfos << "Turning off Windows error reporting." << llendl; + // LL_INFOS() << "Turning off Windows error reporting." << LL_ENDL; disableWinErrorReporting(); #ifndef LL_RELEASE_FOR_DOWNLOAD LLWinDebug::instance().init(); #endif - return LLAppViewer::init(); +#if LL_WINDOWS +#if LL_SEND_CRASH_REPORTS + + + LLAppViewer* pApp = LLAppViewer::instance(); + pApp->initCrashReporting(); + +#endif +#endif + + bool success = LLAppViewer::init(); + + return success; } bool LLAppViewerWin32::cleanup() @@ -353,18 +545,28 @@ bool LLAppViewerWin32::cleanup() gDXHardware.cleanup(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + LLWinDebug::instance().cleanup(); +#endif + + if (mIsConsoleAllocated) + { + FreeConsole(); + mIsConsoleAllocated = false; + } + return result; } -bool LLAppViewerWin32::initLogging() +void LLAppViewerWin32::initLoggingAndGetLastDuration() { - return LLAppViewer::initLogging(); + LLAppViewer::initLoggingAndGetLastDuration(); } void LLAppViewerWin32::initConsole() { // pop up debug console - create_console(); + mIsConsoleAllocated = create_console(); return LLAppViewer::initConsole(); } @@ -388,11 +590,9 @@ bool LLAppViewerWin32::initHardwareTest() // if (FALSE == gSavedSettings.getBOOL("NoHardwareProbe")) { - BOOL vram_only = !gSavedSettings.getBOOL("ProbeHardwareOnStartup"); - // per DEV-11631 - disable hardware probing for everything // but vram. - vram_only = TRUE; + BOOL vram_only = TRUE; LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware")); @@ -416,7 +616,7 @@ bool LLAppViewerWin32::initHardwareTest() if (OSBTN_NO== button) { LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL; - LLWeb::loadURLExternal(DIRECTX_9_URL, false); + LLWeb::loadURLExternal("http://secondlife.com/support/", false); return false; } gWarningSettings.setBOOL("AboutDirectX9", FALSE); @@ -440,7 +640,11 @@ bool LLAppViewerWin32::initHardwareTest() LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; } - gGLManager.mVRAM = gDXHardware.getVRAM(); + if (gGLManager.mVRAM == 0) + { + gGLManager.mVRAM = gDXHardware.getVRAM(); + } + LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; return true; @@ -481,30 +685,55 @@ bool LLAppViewerWin32::restoreErrorTrap() //return LLWinDebug::checkExceptionHandler(); } -void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) +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; - const char* arg_str = logger_name; + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); + std::string appname = gDirUtilp->getExecutableFilename(); - // *NOTE:Mani - win_crash_logger.exe no longer parses command line options. - if(reportFreeze) + S32 slen = logdir.length() -1; + S32 end = slen; + while (logdir.at(end) == '/' || logdir.at(end) == '\\') end--; + + if (slen !=end) { - // Spawn crash logger. - // NEEDS to wait until completion, otherwise log files will get smashed. - _spawnl(_P_WAIT, exe_path.c_str(), arg_str, NULL); + logdir = logdir.substr(0,end+1); } - else + //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=wstringize(exe_path); + + std::wstring arg_wstr; + arg_wstr=wstringize(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()' { - S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING); - if(cb != CRASH_BEHAVIOR_NEVER_SEND) - { - _spawnl(_P_NOWAIT, exe_path.c_str(), arg_str, NULL); - } - } + LL_WARNS("CrashReport Launch") << "CreateProcess failed " << GetLastError() << LL_ENDL; + return; + } } //virtual @@ -518,7 +747,7 @@ bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url) if (other_window != NULL) { - lldebugs << "Found other window with the name '" << getWindowTitle() << "'" << llendl; + LL_DEBUGS() << "Found other window with the name '" << getWindowTitle() << "'" << LL_ENDL; COPYDATASTRUCT cds; const S32 SLURL_MESSAGE_TYPE = 0; cds.dwData = SLURL_MESSAGE_TYPE; @@ -526,8 +755,8 @@ bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url) cds.lpData = (void*)url.c_str(); LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds); - lldebugs << "SendMessage(WM_COPYDATA) to other window '" - << getWindowTitle() << "' returned " << msg_result << llendl; + LL_DEBUGS() << "SendMessage(WM_COPYDATA) to other window '" + << getWindowTitle() << "' returned " << msg_result << LL_ENDL; return true; } return false; @@ -559,7 +788,7 @@ std::string LLAppViewerWin32::generateSerialNumber() } else { - llwarns << "GetVolumeInformation failed" << llendl; + LL_WARNS() << "GetVolumeInformation failed" << LL_ENDL; } return serial_md5; } |