diff options
Diffstat (limited to 'indra/newview/llappviewerwin32.cpp')
-rw-r--r-- | indra/newview/llappviewerwin32.cpp | 381 |
1 files changed, 252 insertions, 129 deletions
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index fb726e7c97..d328567a0e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -2,35 +2,36 @@ * @file llappviewerwin32.cpp * @brief The LLAppViewerWin32 class definitions * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" +#if defined(_DEBUG) +# if _MSC_VER >= 1400 // Visual C++ 2005 or later +# define WINDOWS_CRT_MEM_CHECKS 1 +# endif +#endif + #include "llappviewerwin32.h" #include "llmemtype.h" @@ -50,56 +51,54 @@ #include "llweb.h" #include "llsecondlifeurls.h" -#include "llwindebug.h" - #include "llviewernetwork.h" #include "llmd5.h" +#include "llfindlocale.h" #include "llcommandlineparser.h" +#include "lltrans.h" -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - - // Translate the signals/exceptions into cross-platform stuff - // Windows implementation - llinfos << "Entering Windows Exception Handler..." << llendl; - - // Make sure the user sees something to indicate that the app crashed. - LONG retval; - - if (LLApp::isError()) - { - llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; - } +#ifndef LL_RELEASE_FOR_DOWNLOAD +#include "llwindebug.h" +#endif - // Generate a minidump if we can. - // Before we wake the error thread... - // Which will start the crash reporting. - LLWinDebug::handleException(exception_infop); - - // Flag status to error, so thread_error starts its work - LLApp::setError(); +// *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 +#ifdef LL_MSVC7 +extern "C" { + void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) + { + llerrs << _Message << llendl; + } +} +#endif +#endif - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); +const std::string LLAppViewerWin32::sWindowClass = "Second Life"; + +// 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 +// if another instance of a second life app (this vers. or later) +// is running. +// *NOTE: Do not use this method to run a single instance of the app. +// This is intended to help debug problems with the cross-platform +// locked file method used for that purpose. +bool create_app_mutex() +{ + bool result = true; + LPCWSTR unique_mutex_name = L"SecondLifeAppMutex"; + HANDLE hMutex; + hMutex = CreateMutex(NULL, TRUE, unique_mutex_name); + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + result = false; } - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; + return result; } - +//#define DEBUGGING_SEH_FILTER 1 #if DEBUGGING_SEH_FILTER # define WINMAIN DebuggingWinMain #else @@ -112,40 +111,65 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, 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 + // 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 + + _CrtSetDbgFlag(0); // default, just making explicit + + ULONG ulEnableLFH = 2; + HANDLE* hHeaps = new HANDLE[MAX_HEAPS]; + num_heaps = GetProcessHeaps(MAX_HEAPS, hHeaps); + for(S32 i = 0; i < num_heaps; i++) + { + bool success = HeapSetInformation(hHeaps[i], HeapCompatibilityInformation, &ulEnableLFH, sizeof(ulEnableLFH)); + if (success) + heap_enable_lfh_error[i] = 0; + else + heap_enable_lfh_error[i] = GetLastError(); + } +#endif // *FIX: global gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - - // *FIX:Mani This method is poorly named, since the exception - // is now handled by LLApp. - bool ok = LLWinDebug::setupExceptionHandler(); - // Actually here's the exception setup. - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(viewer_windows_exception_handler); - if (!prev_filter) - { - llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl; - ok = FALSE; - } - if (prev_filter != LLWinDebug::handleException) - { - llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl; - ok = FALSE; - } - viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - ok = viewer_app_ptr->init(); + // 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); + + bool ok = viewer_app_ptr->init(); if(!ok) { llwarns << "Application init failed." << llendl; return -1; } - - // Run the application main loop + + // 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; + 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; + } + } + } + + // Run the application main loop if(!LLApp::isQuitting()) { viewer_app_ptr->mainLoop(); @@ -158,10 +182,47 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, // the assumption is that the error handler is responsible for doing // app cleanup if there was a problem. // - viewer_app_ptr->cleanup(); +#if WINDOWS_CRT_MEM_CHECKS + llinfos << "CRT Checking memory:" << llendflush; + if (!_CrtCheckMemory()) + { + llwarns << "_CrtCheckMemory() failed at prior to cleanup!" << llendflush; + } + else + { + llinfos << " No corruption detected." << llendflush; + } +#endif + + gGLActive = TRUE; + + viewer_app_ptr->cleanup(); + +#if WINDOWS_CRT_MEM_CHECKS + llinfos << "CRT Checking memory:" << llendflush; + if (!_CrtCheckMemory()) + { + llwarns << "_CrtCheckMemory() failed after cleanup!" << llendflush; + } + else + { + llinfos << " No corruption detected." << llendflush; + } +#endif + } delete viewer_app_ptr; viewer_app_ptr = NULL; + + //start updater + if(LLAppViewer::sUpdaterInfo) + { + _spawnl(_P_NOWAIT, LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), LLAppViewer::sUpdaterInfo->mParams.str().c_str(), NULL); + + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + } + return 0; } @@ -279,6 +340,10 @@ bool LLAppViewerWin32::init() llinfos << "Turning off Windows error reporting." << llendl; disableWinErrorReporting(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + LLWinDebug::instance().init(); +#endif + return LLAppViewer::init(); } @@ -291,6 +356,11 @@ bool LLAppViewerWin32::cleanup() return result; } +bool LLAppViewerWin32::initLogging() +{ + return LLAppViewer::initLogging(); +} + void LLAppViewerWin32::initConsole() { // pop up debug console @@ -300,7 +370,7 @@ void LLAppViewerWin32::initConsole() void write_debug_dx(const char* str) { - LLString value = gDebugInfo["DXInfo"].asString(); + std::string value = gDebugInfo["DXInfo"].asString(); value += str; gDebugInfo["DXInfo"] = value; } @@ -320,97 +390,150 @@ bool LLAppViewerWin32::initHardwareTest() { BOOL vram_only = !gSavedSettings.getBOOL("ProbeHardwareOnStartup"); - LLSplashScreen::update("Detecting hardware..."); + // per DEV-11631 - disable hardware probing for everything + // but vram. + vram_only = TRUE; + + LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware")); - llinfos << "Attempting to poll DirectX for hardware info" << llendl; + LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL; gDXHardware.setWriteDebugFunc(write_debug_dx); BOOL probe_ok = gDXHardware.getInfo(vram_only); if (!probe_ok - && gSavedSettings.getWarning("AboutDirectX9")) + && gWarningSettings.getBOOL("AboutDirectX9")) { - llinfos << "DirectX probe failed, alerting user." << llendl; + LL_WARNS("AppInit") << "DirectX probe failed, alerting user." << LL_ENDL; // Warn them that runnin without DirectX 9 will // not allow us to tell them about driver issues std::ostringstream msg; - msg << - LLAppViewer::instance()->getSecondLifeTitle() << " is unable to detect DirectX 9.0b or greater.\n" - "\n" << - LLAppViewer::instance()->getSecondLifeTitle() << " uses DirectX to detect hardware and/or\n" - "outdated drivers that can cause stability problems,\n" - "poor performance and crashes. While you can run\n" << - LLAppViewer::instance()->getSecondLifeTitle() << " without it, we highly recommend running\n" - "with DirectX 9.0b\n" - "\n" - "Do you wish to continue?\n"; + msg << LLTrans::getString ("MBNoDirectX"); S32 button = OSMessageBox( - msg.str().c_str(), - "Warning", + msg.str(), + LLTrans::getString("MBWarning"), OSMB_YESNO); if (OSBTN_NO== button) { - llinfos << "User quitting after failed DirectX 9 detection" << llendl; - LLWeb::loadURLExternal(DIRECTX_9_URL); + LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL; + LLWeb::loadURLExternal(DIRECTX_9_URL, false); return false; } - gSavedSettings.setWarning("AboutDirectX9", FALSE); + gWarningSettings.setBOOL("AboutDirectX9", FALSE); } - llinfos << "Done polling DirectX for hardware info" << llendl; + LL_DEBUGS("AppInit") << "Done polling DirectX for hardware info" << LL_ENDL; // Only probe once after installation gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE); // Disable so debugger can work - std::ostringstream splash_msg; - splash_msg << "Loading " << LLAppViewer::instance()->getSecondLifeTitle() << "..."; + std::string splash_msg; + LLStringUtil::format_map_t args; + args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle(); + splash_msg = LLTrans::getString("StartupLoading", args); - LLSplashScreen::update(splash_msg.str().c_str()); + LLSplashScreen::update(splash_msg); } - if (!LLWinDebug::setupExceptionHandler()) + if (!restoreErrorTrap()) { - llwarns << " Someone took over my exception handler (post hardware probe)!" << llendl; + LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; } gGLManager.mVRAM = gDXHardware.getVRAM(); - llinfos << "Detected VRAM: " << gGLManager.mVRAM << llendl; + LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; return true; } bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) { - return clp.parseCommandLineString(mCmdLine); + if (!clp.parseCommandLineString(mCmdLine)) + { + return false; + } + + // Find the system language. + FL_Locale *locale = NULL; + FL_Success success = FL_FindLocale(&locale, FL_MESSAGES); + if (success != 0) + { + if (success >= 2 && locale->lang) // confident! + { + LL_INFOS("AppInit") << "Language: " << ll_safe_string(locale->lang) << LL_ENDL; + LL_INFOS("AppInit") << "Location: " << ll_safe_string(locale->country) << LL_ENDL; + LL_INFOS("AppInit") << "Variant: " << ll_safe_string(locale->variant) << LL_ENDL; + LLControlVariable* c = gSavedSettings.getControl("SystemLanguage"); + if(c) + { + c->setValue(std::string(locale->lang), false); + } + } + } + FL_FreeLocale(&locale); + + return true; +} + +bool LLAppViewerWin32::restoreErrorTrap() +{ + return true; + //return LLWinDebug::checkExceptionHandler(); } -void LLAppViewerWin32::handleCrashReporting() +void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) { - // Windows only behaivor. Spawn win crash reporter. - std::string exe_path = gDirUtilp->getAppRODataDir(); + const char* logger_name = "win_crash_logger.exe"; + std::string exe_path = gDirUtilp->getExecutableDir(); exe_path += gDirUtilp->getDirDelimiter(); - exe_path += "win_crash_logger.exe"; + exe_path += logger_name; - std::string arg_string = "-user "; - arg_string += gGridName; + const char* arg_str = logger_name; - switch(getCrashBehavior()) + // *NOTE:Mani - win_crash_logger.exe no longer parses command line options. + if(reportFreeze) { - case CRASH_BEHAVIOR_ASK: - default: - arg_string += " -dialog "; - _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL); - break; - - case CRASH_BEHAVIOR_ALWAYS_SEND: - _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL); - break; - - case CRASH_BEHAVIOR_NEVER_SEND: - break; + // Spawn crash logger. + // NEEDS to wait until completion, otherwise log files will get smashed. + _spawnl(_P_WAIT, exe_path.c_str(), arg_str, NULL); } + else + { + S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING); + if(cb != CRASH_BEHAVIOR_NEVER_SEND) + { + _spawnl(_P_NOWAIT, exe_path.c_str(), arg_str, NULL); + } + } +} + +//virtual +bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url) +{ + wchar_t window_class[256]; /* Flawfinder: ignore */ // Assume max length < 255 chars. + mbstowcs(window_class, sWindowClass.c_str(), 255); + window_class[255] = 0; + // Use the class instead of the window name. + HWND other_window = FindWindow(window_class, NULL); + + if (other_window != NULL) + { + lldebugs << "Found other window with the name '" << getWindowTitle() << "'" << llendl; + COPYDATASTRUCT cds; + const S32 SLURL_MESSAGE_TYPE = 0; + cds.dwData = SLURL_MESSAGE_TYPE; + cds.cbData = url.length() + 1; + 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; + return true; + } + return false; } + std::string LLAppViewerWin32::generateSerialNumber() { char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore |