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.cpp381
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