diff --git a/.hgtags b/.hgtags
index aeb1ebadeaedb2e0ce790bed3b467146df7c8288..d0b08ec1ea3c488d62f588f1bad6069b0d1699cf 100755
--- a/.hgtags
+++ b/.hgtags
@@ -477,3 +477,4 @@ dcb4981ce255841b6083d8f65444b65d5a733a17 3.7.1-release
 b842534cb4d76c9ef87676a62b1d2d19e79c015f 3.7.2-release
 962d3f98955bfc7310a7867c8cbc3df075e54aa9 3.7.3-release
 d076568ff7883b41c149e6afb421f39c29dbfe2b 3.7.4-release
+fc066b82343fca51f9c1b8eda0abc6bee9bb4503 3.7.5-release
diff --git a/autobuild.xml b/autobuild.xml
index 91d7574e00e43bc13ede0ad0d6f07da36ee5b569..cd2a0855202abc0fd4cf446370f4312274c15384 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -786,9 +786,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d812a6dfcabe6528198a3191068dac09</string>
+              <string>a1e519d08c507c12f9d412b2ae8328c8</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/CYGWIN/installer/google_breakpad-0.0.0-rev1099-windows-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/279804/arch/CYGWIN/installer/google_breakpad-0.0.0-rev1099-windows-20130813.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake
index 96e22791ec8a239e59766ec23b06b901f12309ee..7f9ba4ea8ea8a0a1ff237cc4e0d53daf211f5120 100755
--- a/indra/cmake/GoogleBreakpad.cmake
+++ b/indra/cmake/GoogleBreakpad.cmake
@@ -13,7 +13,7 @@ else (STANDALONE)
     set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client)
   endif (LINUX)
   if (WINDOWS)
-    set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common)
+    set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common)
   endif (WINDOWS)
   # yes, this does look dumb, no, it's not incorrect
   #
diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp
index 99d0ad7e14060786688490ba0ba577cc61e8521b..d4e7ad7be33d23c8c687d8d31ed970fbc5621e26 100755
--- a/indra/linux_crash_logger/linux_crash_logger.cpp
+++ b/indra/linux_crash_logger/linux_crash_logger.cpp
@@ -26,6 +26,7 @@
 
 #include "linden_common.h"
 #include "llcrashloggerlinux.h"
+#include "llsdutil.h"
 
 int main(int argc, char **argv)
 {
@@ -34,6 +35,16 @@ int main(int argc, char **argv)
 	LLCrashLoggerLinux app;
 	app.parseCommandOptions(argc, argv);
 
+    LLSD options = LLApp::instance()->getOptionData(
+                        LLApp::PRIORITY_COMMAND_LINE);
+                        //LLApp::PRIORITY_RUNTIME_OVERRIDE);
+
+    
+    if (!(options.has("pid") && options.has("dumpdir")))
+    {
+        llwarns << "Insufficient parameters to crash report." << llendl;
+    }
+
 	if (! app.init())
 	{
 		llwarns << "Unable to initialize application." << llendl;
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
index 62465f9937d486fd780fe4bd5a58738e35b89fcf..871d6377cb262203bb0f37d97577a163af076a92 100755
--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
+++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
@@ -136,6 +136,7 @@ bool LLCrashLoggerLinux::mainLoop()
 bool LLCrashLoggerLinux::cleanup()
 {
 	commonCleanup();
+    mKeyMaster.releaseMaster();
 	return true;
 }
 
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 67a98d5fb89d9c85b979be3cf863c9f7e601712d..5c8fff051f53886f57ad3d4db183e889bb9305c7 100755
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -46,8 +46,8 @@
 #include "llstl.h" // for DeletePointer()
 #include "llstring.h"
 #include "lleventtimer.h"
-
 #include "google_breakpad/exception_handler.h"
+#include "stringize.h"
 
 //
 // Signal handling
@@ -55,6 +55,8 @@
 // Windows uses structured exceptions, so it's handled a bit differently.
 //
 #if LL_WINDOWS
+#include "windows.h"
+
 LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);
 BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
 bool windows_post_minidump_callback(const wchar_t* dump_path,
@@ -71,7 +73,9 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *);
 
 #if LL_LINUX
 #include "google_breakpad/minidump_descriptor.h"
-bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded);
+static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, 
+                                   void* context, 
+                                   bool succeeded);
 #else
 // Called by breakpad exception handler after the minidump has been generated.
 bool unix_post_minidump_callback(const char *dump_dir,
@@ -109,11 +113,6 @@ BOOL LLApp::sLogInSignal = FALSE;
 LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status
 LLAppErrorHandler LLApp::sErrorHandler = NULL;
 BOOL LLApp::sErrorThreadRunning = FALSE;
-#if !LL_WINDOWS
-LLApp::child_map LLApp::sChildMap;
-LLAtomicU32* LLApp::sSigChildCount = NULL;
-LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
-#endif
 
 
 LLApp::LLApp() : mThreadErrorp(NULL)
@@ -128,11 +127,6 @@ void LLApp::commonCtor()
 
 	LLCommon::initClass();
 
-#if !LL_WINDOWS
-	// This must be initialized before the error handler.
-	sSigChildCount = new LLAtomicU32(0);
-#endif
-
 	// initialize the options structure. We need to make this an array
 	// because the structured data will not auto-allocate if we
 	// reference an invalid location with the [] operator.
@@ -149,12 +143,13 @@ void LLApp::commonCtor()
 
 	// Set the application to this instance.
 	sApplication = this;
-	
+
 	mExceptionHandler = 0;
 	
 	// initialize the buffer to write the minidump filename to
 	// (this is used to avoid allocating memory in the crash handler)
-	memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH);
+	memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH);
+	mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
 }
 
 LLApp::LLApp(LLErrorThread *error_thread) :
@@ -166,10 +161,6 @@ LLApp::LLApp(LLErrorThread *error_thread) :
 
 LLApp::~LLApp()
 {
-#if !LL_WINDOWS
-	delete sSigChildCount;
-	sSigChildCount = NULL;
-#endif
 
 	// reclaim live file memory
 	std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer());
@@ -244,6 +235,20 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
 		}
 		++ii;
 		value.assign(argv[ii]);
+
+#if LL_WINDOWS
+		//Windows changed command line parsing.  Deal with it.
+		S32 slen = value.length() - 1;
+		S32 start = 0;
+		S32 end = slen;
+		if (argv[ii][start]=='"')start++;
+		if (argv[ii][end]=='"')end--;
+		if (start!=0 || end!=slen) 
+		{
+			value = value.substr (start,end);
+		}
+#endif
+
 		commands[name] = value;
 	}
 	setOptionData(PRIORITY_COMMAND_LINE, commands);
@@ -288,6 +293,32 @@ void LLApp::stepFrame()
 	mRunner.run();
 }
 
+#if LL_WINDOWS
+//The following code is needed for 32-bit apps on 64-bit windows to keep it from eating
+//crashes.   It is a lovely undocumented 'feature' in SP1 of Windows 7. An excellent
+//in-depth article on the issue may be found here:  http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesn-work/
+void EnableCrashingOnCrashes()
+{
+	typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
+	typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
+	const DWORD EXCEPTION_SWALLOWING = 0x1;
+
+	HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+	tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
+		"GetProcessUserModeExceptionPolicy");
+	tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
+		"SetProcessUserModeExceptionPolicy");
+	if (pGetPolicy && pSetPolicy)
+	{
+		DWORD dwFlags;
+		if (pGetPolicy(&dwFlags))
+		{
+			// Turn off the filter
+			pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
+		}
+	}
+}
+#endif
 
 void LLApp::setupErrorHandling()
 {
@@ -295,7 +326,10 @@ void LLApp::setupErrorHandling()
 	// occasionally checks to see if the app is in an error state, and sees if it needs to be run.
 
 #if LL_WINDOWS
+
 #if LL_SEND_CRASH_REPORTS
+	EnableCrashingOnCrashes();
+
 	// This sets a callback to handle w32 signals to the console window.
 	// The viewer shouldn't be affected, sicne its a windowed app.
 	SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
@@ -304,8 +338,44 @@ void LLApp::setupErrorHandling()
 	if(mExceptionHandler == 0)
 	{
 		llwarns << "adding breakpad exception handler" << llendl;
-		mExceptionHandler = new google_breakpad::ExceptionHandler(
-			L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL);
+
+		std::wstring wpipe_name;
+		wpipe_name =  mCrashReportPipeStr + wstringize(getPid());
+
+		const std::wstring wdump_path(wstringize(mDumpPath));
+
+		int retries = 30;
+		for (; retries > 0; --retries)
+		{
+			if (mExceptionHandler != 0) delete mExceptionHandler;
+
+			mExceptionHandler = new google_breakpad::ExceptionHandler(
+														wdump_path,		
+														NULL,		//No filter
+														windows_post_minidump_callback,
+														0,
+														google_breakpad::ExceptionHandler::HANDLER_ALL,
+														MiniDumpNormal, //Generate a 'normal' minidump.
+														wpipe_name.c_str(),
+														NULL);  //No custom client info.
+			if (mExceptionHandler->IsOutOfProcess())
+			{
+				LL_INFOS("CRASHREPORT") << "Successfully attached to Out of Process exception handler." << LL_ENDL;
+				break;
+			}
+			else
+			{
+				LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler.  " << retries << " retries remaining." << LL_ENDL; 
+				::Sleep(100);  //Wait a tick and try again.
+			}
+		}
+
+		if (retries == 0) LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler." << LL_ENDL;
+
+		if (mExceptionHandler)
+		{
+			mExceptionHandler->set_handle_debug_exceptions(true);
+		}
 	}
 #endif
 #else
@@ -355,14 +425,17 @@ void LLApp::setupErrorHandling()
 
 	if(installHandler && (mExceptionHandler == 0))
 	{
-		std::string dumpPath = "/tmp/";
-		mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
+		mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
 	}
 #elif LL_LINUX
 	if(installHandler && (mExceptionHandler == 0))
 	{
-		google_breakpad::MinidumpDescriptor desc("/tmp");
-	        new google_breakpad::ExceptionHandler(desc, 0, &unix_minidump_callback, 0, true, 0);
+		if (mDumpPath.empty())
+		{
+			mDumpPath = "/tmp";
+		}
+		google_breakpad::MinidumpDescriptor desc(mDumpPath);
+	    mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1);
 	}
 #endif
 
@@ -418,19 +491,35 @@ void LLApp::setError()
 
 void LLApp::setMiniDumpDir(const std::string &path)
 {
+	if (path.empty())
+	{
+		mDumpPath = "/tmp";
+	}
+	else
+	{
+		mDumpPath = path;
+	}
+
 	if(mExceptionHandler == 0) return;
 #ifdef LL_WINDOWS
 	wchar_t buffer[MAX_MINDUMP_PATH_LENGTH];
-	mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH);
+	mbstowcs(buffer, mDumpPath.c_str(), MAX_MINDUMP_PATH_LENGTH);
 	mExceptionHandler->set_dump_path(std::wstring(buffer));
 #elif LL_LINUX
-        google_breakpad::MinidumpDescriptor desc(path);
+        //google_breakpad::MinidumpDescriptor desc("/tmp");	//path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
+        google_breakpad::MinidumpDescriptor desc(mDumpPath);	//path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
 	mExceptionHandler->set_minidump_descriptor(desc);
 #else
-	mExceptionHandler->set_dump_path(path);
+	mExceptionHandler->set_dump_path(mDumpPath);
 #endif
 }
 
+void LLApp::setDebugFileNames(const std::string &path)
+{
+  	mStaticDebugFileName = path + "static_debug_info.log";
+  	mDynamicDebugFileName = path + "dynamic_debug_info.log";
+}
+
 void LLApp::writeMiniDump()
 {
 	if(mExceptionHandler == 0) return;
@@ -507,34 +596,11 @@ bool LLApp::isCrashloggerDisabled()
 	return (sDisableCrashlogger == TRUE); 
 }
 
-#if !LL_WINDOWS
-// static
-U32 LLApp::getSigChildCount()
-{
-	if (sSigChildCount)
-	{
-		return U32(*sSigChildCount);
-	}
-	return 0;
-}
-
-// static
-void LLApp::incSigChildCount()
-{
-	if (sSigChildCount)
-	{
-		(*sSigChildCount)++;
-	}
-}
-
-#endif
-
-
 // static
 int LLApp::getPid()
 {
 #if LL_WINDOWS
-	return 0;
+    return GetCurrentProcessId();
 #else
 	return getpid();
 #endif
@@ -610,43 +676,6 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
 } 
 
 #else //!LL_WINDOWS
-void LLApp::setChildCallback(pid_t pid, LLAppChildCallback callback)
-{
-	LLChildInfo child_info;
-	child_info.mCallback = callback;
-	LLApp::sChildMap[pid] = child_info;
-}
-
-void LLApp::setDefaultChildCallback(LLAppChildCallback callback)
-{
-	LLApp::sDefaultChildCallback = callback;
-}
-
-pid_t LLApp::fork()
-{
-	fflush(NULL); // flush all buffers before the child inherits them
-	pid_t pid = ::fork();
-	if( pid < 0 )
-	{
-		int system_error = errno;
-		llwarns << "Unable to fork! Operating system error code: "
-				<< system_error << llendl;
-	}
-	else if (pid == 0)
-	{
-		// Sleep a bit to allow the parent to set up child callbacks.
-		ms_sleep(10);
-
-		// We need to disable signal handling, because we don't have a
-		// signal handling thread anymore.
-		setupErrorHandling();
-	}
-	else
-	{
-		llinfos << "Forked child process " << pid << llendl;
-	}
-	return pid;
-}
 
 void setup_signals()
 {
@@ -747,19 +776,6 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 			llinfos << "Signal handler - Got SIGCHLD from " << info->si_pid << llendl;
 		}
 
-		// Check result code for all child procs for which we've
-		// registered callbacks THIS WILL NOT WORK IF SIGCHLD IS SENT
-		// w/o killing the child (Go, launcher!)
-		// TODO: Now that we're using SIGACTION, we can actually
-		// implement the launcher behavior to determine who sent the
-		// SIGCHLD even if it doesn't result in child termination
-		if (LLApp::sChildMap.count(info->si_pid))
-		{
-			LLApp::sChildMap[info->si_pid].mGotSigChild = TRUE;
-		}
-		
-		LLApp::incSigChildCount();
-
 		return;
 	case SIGABRT:
 		// Abort just results in termination of the app, no funky error handling.
@@ -880,21 +896,26 @@ bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_
 	// heap allocations in a crash handler.
 	
 	// path format: <dump_dir>/<minidump_id>.dmp
-	int dirPathLength = strlen(minidump_desc.path());
+	
+	//HACK:  *path points to the buffer in getMiniDumpFilename which has already allocated space
+	//to avoid doing allocation during crash.
+	char * path = LLApp::instance()->getMiniDumpFilename();
+	int dir_path_len = strlen(path);
 	
 	// The path must not be truncated.
-	llassert((dirPathLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
+	S32 remaining =  LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len;
+
+	llassert( (remaining - strlen(minidump_desc.path())) > 5);
 	
-	char * path = LLApp::instance()->getMiniDumpFilename();
-	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
-	strncpy(path, minidump_desc.path(), remaining);
-	remaining -= dirPathLength;
-	path += dirPathLength;
-	if (remaining > 0 && dirPathLength > 0 && path[-1] != '/')
+	path += dir_path_len;
+
+	if (dir_path_len > 0 && path[-1] != '/')
 	{
 		*path++ = '/';
 		--remaining;
 	}
+
+	strncpy(path, minidump_desc.path(), remaining);
 	
 	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
 	LLApp::runErrorHandler();
@@ -942,7 +963,7 @@ bool unix_post_minidump_callback(const char *dump_dir,
 		strncpy(path, ".dmp", remaining);
 	}
 	
-	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+	llinfos << "generated minidump: " << path << llendl;
 	LLApp::runErrorHandler();
 	
 #ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -966,6 +987,7 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
 	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
 	size_t bytesUsed;
 
+	LL_INFOS("MINIDUMPCALLBACK") << "Dump file was generated." << LL_ENDL;
 	bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining));
 	remaining -= bytesUsed;
 	path += bytesUsed;
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index afa06df23e1e680b394d7b83b84c94cf52ddea8b..828965b1fabfdd4ea26da3c7971a1dfd8c3fb39f 100755
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -31,7 +31,6 @@
 #include "llrun.h"
 #include "llsd.h"
 #include "lloptioninterface.h"
-
 // Forward declarations
 template <typename Type> class LLAtomic32;
 typedef LLAtomic32<U32> LLAtomicU32;
@@ -42,7 +41,6 @@ class LLLiveFile;
 #endif
 
 typedef void (*LLAppErrorHandler)();
-typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
 
 #if !LL_WINDOWS
 extern S32 LL_SMACKDOWN_SIGNAL;
@@ -51,13 +49,6 @@ extern S32 LL_HEARTBEAT_SIGNAL;
 // Clear all of the signal handlers (which we want to do for the child process when we fork
 void clear_signals();
 
-class LLChildInfo
-{
-public:
-	LLChildInfo() : mGotSigChild(FALSE), mCallback(NULL) {}
-	BOOL mGotSigChild;
-	LLAppChildCallback mCallback;
-};
 #endif
 
 namespace google_breakpad {
@@ -206,10 +197,6 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 	static bool isQuitting();
 	static bool isError();
 	static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
-#if !LL_WINDOWS
-	static U32  getSigChildCount();
-	static void incSigChildCount();
-#endif
 	static int getPid();
 
 	/** @name Error handling methods */
@@ -238,32 +225,16 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 
 	// change the directory where Breakpad minidump files are written to
 	void setMiniDumpDir(const std::string &path);
+    void setDebugFileNames(const std::string &path);
 
 	// Return the Google Breakpad minidump filename after a crash.
-	char *getMiniDumpFilename() { return minidump_path; }
+	char *getMiniDumpFilename() { return mMinidumpPath; }
+    std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
+    std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
 
 	// Write out a Google Breakpad minidump file.
 	void writeMiniDump();
 
-#if !LL_WINDOWS
-	//
-	// Child process handling (Unix only for now)
-	//
-	// Set a callback to be run on exit of a child process
-	// WARNING!  This callback is run from the signal handler due to
-	// Linux threading requiring waitpid() to be called from the thread that spawned the process.
-	// At some point I will make this more behaved, but I'm not going to fix this right now - djs
-	void setChildCallback(pid_t pid, LLAppChildCallback callback);
-
-    // The child callback to run if no specific handler is set
-	void setDefaultChildCallback(LLAppChildCallback callback); 
-	
-    // Fork and do the proper signal handling/error handling mojo
-	// *NOTE: You need to make sure your signal handling callback is
-	// correct after you fork, because not all threads are duplicated
-	// when you fork!
-	pid_t fork(); 
-#endif
 
 	/**
 	  * @brief Get a reference to the application runner
@@ -286,13 +257,9 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 	static EAppStatus sStatus; // Reflects current application status
 	static BOOL sErrorThreadRunning; // Set while the error thread is running
 	static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
+	std::wstring mCrashReportPipeStr;  //Name of pipe to use for crash reporting.
 
-#if !LL_WINDOWS
-	static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
-	typedef std::map<pid_t, LLChildInfo> child_map; // Map key is a PID
-	static child_map sChildMap;
-	static LLAppChildCallback sDefaultChildCallback;
-#endif
+    std::string mDumpPath;  //output path for google breakpad.  Dependency workaround.
 
 	/**
 	  * @brief This method is called once a frame to do once a frame tasks.
@@ -303,7 +270,10 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 	void startErrorThread();
 	
 	// Contains the filename of the minidump file after a crash.
-	char minidump_path[MAX_MINDUMP_PATH_LENGTH];
+	char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
+    
+    std::string mStaticDebugFileName;
+    std::string mDynamicDebugFileName;
 
 	// *NOTE: On Windows, we need a routine to reset the structured
 	// exception handler when some evil driver has taken it over for
diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp
index 950fcd6e8392e52c437c647b15c2522fa07b3976..ebfbe19ff7705635a1cee3bb8e35350ecba86d0d 100755
--- a/indra/llcommon/llerrorthread.cpp
+++ b/indra/llcommon/llerrorthread.cpp
@@ -109,79 +109,8 @@ void LLErrorThread::run()
 	llinfos << "thread_error - Waiting for an error" << llendl;
 
 	S32 counter = 0;
-#if !LL_WINDOWS
-	U32 last_sig_child_count = 0;
-#endif
 	while (! (LLApp::isError() || LLApp::isStopped()))
 	{
-#if !LL_WINDOWS
-		// Check whether or not the main thread had a sig child we haven't handled.
-		U32 current_sig_child_count = LLApp::getSigChildCount();
-		if (last_sig_child_count != current_sig_child_count)
-		{
-			int status = 0;
-			pid_t child_pid = 0;
-			last_sig_child_count = current_sig_child_count;
-			if (LLApp::sLogInSignal)
-			{
-				llinfos << "thread_error handling SIGCHLD #" << current_sig_child_count << llendl;
-			}
-			for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin(); iter != LLApp::sChildMap.end();)
-			{
-				child_pid = iter->first;
-				LLChildInfo &child_info = iter->second;
-				// check the status of *all* children, in case we missed a signal
-				if (0 != waitpid(child_pid, &status, WNOHANG))
-				{
-					bool exited = false;
-					int exit_status = -1;
-					get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
-
-					if (child_info.mCallback)
-					{
-						if (LLApp::sLogInSignal)
-						{
-							llinfos << "Signal handler - Running child callback" << llendl;
-						}
-						child_info.mCallback(child_pid, exited, status);
-					}
-					LLApp::sChildMap.erase(iter++);
-				}
-				else
-				{
-					// Child didn't terminate, yet we got a sigchild somewhere...
-					if (child_info.mGotSigChild && child_info.mCallback)
-					{
-						child_info.mCallback(child_pid, false, 0);
-					}
-					child_info.mGotSigChild = FALSE;
-					iter++;
-				}
-			}
-
-			// check the status of *all* children, in case we missed a signal
-			// Same as above, but use the default child callback
-			while(0 < (child_pid = waitpid( -1, &status, WNOHANG )))
-			{
-				if (0 != waitpid(child_pid, &status, WNOHANG))
-				{
-					bool exited = false;
-					int exit_status = -1;
-					get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
-					if (LLApp::sDefaultChildCallback)
-					{
-						if (LLApp::sLogInSignal)
-						{
-							llinfos << "Signal handler - Running default child callback" << llendl;
-						}
-						LLApp::sDefaultChildCallback(child_pid, true, status);
-					}
-				}
-			}
-		}
-
-
-#endif
 		ms_sleep(10);
 		counter++;
 	}
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c3a0f0bfe0492d9a8e931f3dd5097bd47bf58fcc..761d7f430cfb4a6d6ceb5688a8f51bdc5680e6d7 100755
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -265,6 +265,37 @@ int	LLFile::rename(const std::string& filename, const std::string& newname)
 	return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc);
 }
 
+bool LLFile::copy(const std::string from, const std::string to)
+{
+	bool copied = false;
+	LLFILE* in = LLFile::fopen(from, "rb");		/* Flawfinder: ignore */	 	
+	if (in)	 	
+	{	 	
+		LLFILE* out = LLFile::fopen(to, "wb");		/* Flawfinder: ignore */
+		if (out)
+		{
+			char buf[16384];		/* Flawfinder: ignore */ 	
+			size_t readbytes;
+			bool write_ok = true;
+			while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
+			{
+				if (fwrite(buf, 1, readbytes, out) != readbytes)
+				{
+					LL_WARNS("LLFile") << "Short write" << LL_ENDL; 
+					write_ok = false;
+				}
+			}
+			if ( write_ok )
+			{
+				copied = true;
+			}
+			fclose(out);
+		}
+		fclose(in);
+	}
+	return copied;
+}
+
 int	LLFile::stat(const std::string& filename, llstat* filestatus)
 {
 #if LL_WINDOWS
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index d59e68367e8cc9429a15397c506455999314fc1a..f56b22bf9affda2539ef7d23f962b969610aeeeb 100755
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -75,6 +75,8 @@ class LL_COMMON_API LLFile
 	static	int		rmdir(const std::string& filename);
 	static	int		remove(const std::string& filename);
 	static	int		rename(const std::string& filename,const std::string&	newname);
+	static  bool	copy(const std::string from, const std::string to);
+
 	static	int		stat(const std::string&	filename,llstat*	file_status);
 	static	bool	isdir(const std::string&	filename);
 	static	bool	isfile(const std::string&	filename);
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index f9702868c8eabfd54f0f97c949fca6cf559fb34d..16a19e7021a85e1f39157f2217e16cfe7c44f457 100755
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -518,10 +518,13 @@ LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
 
 LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
 LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
-
 LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
 LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
 
+#if LL_WINDOWS
+inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);}
+#endif
+
 // Length of this UTF32 string in bytes when transformed to UTF8
 LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); 
 
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
index 72f2e58ce122450e9b660d0056b199b2c84425e4..acae74b584e83e98a9efde668a5bb00fd4db51e8 100755
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -31,20 +31,63 @@
 
 #include <sstream>
 #include <boost/lambda/lambda.hpp>
+#include <llstring.h>
 
 /**
- * stringize(item) encapsulates an idiom we use constantly, using
+ * gstringize(item) encapsulates an idiom we use constantly, using
  * operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str()
+ * or their wstring equivalents
  * to render a string expressing some item.
  */
-template <typename T>
-std::string stringize(const T& item)
+template <typename CHARTYPE, typename T>
+std::basic_string<CHARTYPE> gstringize(const T& item)
 {
-    std::ostringstream out;
+    std::basic_ostringstream<CHARTYPE> out;
     out << item;
     return out.str();
 }
 
+/**
+ *partial specialization of stringize for handling wstring
+ *TODO: we should have similar specializations for wchar_t[] but not until it is needed.
+ */
+inline std::string stringize(const std::wstring& item)
+{
+    llwarns << "WARNING:  Possible narrowing" << llendl;
+    
+    std::string s;
+    
+    s = wstring_to_utf8str(item);
+    return gstringize<char>(s);
+}
+
+/**
+ * Specialization of gstringize for std::string return types
+ */
+template <typename T>
+std::string stringize(const T& item)
+{
+    return gstringize<char>(item);
+}
+
+/**
+ * Specialization for generating wstring from string.
+ * Both a convenience function and saves a miniscule amount of overhead.
+ */
+inline std::wstring wstringize(const std::string& item)
+{
+    return gstringize<wchar_t>(item.c_str());
+}
+
+/**
+ * Specialization of gstringize for std::wstring return types
+ */
+template <typename T>
+std::wstring wstringize(const T& item)
+{
+    return gstringize<wchar_t>(item);
+}
+
 /**
  * stringize_f(functor)
  */
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 3d34f23998d5b61748e05bf7f465e0403fbe2385..3e4ca548e55453284bf8b5ea5c6e80a5988ef156 100755
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -67,6 +67,8 @@ namespace tut
             llsd["i"]   = i;
             llsd["d"]   = d;
             llsd["abc"] = abc;
+            def = L"def ghi";
+
         }
 
         char        c;
@@ -76,6 +78,7 @@ namespace tut
         float       f;
         double      d;
         std::string abc;
+		std::wstring def;
         LLSD        llsd;
     };
     typedef test_group<stringize_data> stringize_group;
@@ -92,6 +95,7 @@ namespace tut
         ensure_equals(stringize(f),    "3.14159");
         ensure_equals(stringize(d),    "3.14159");
         ensure_equals(stringize(abc),  "abc def");
+        ensure_equals(stringize(def),  "def ghi"); //Will generate llwarns due to narrowing.
         ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
     }
 
@@ -101,4 +105,20 @@ namespace tut
         ensure_equals(STRINGIZE("c is " << c), "c is c");
         ensure_equals(STRINGIZE(std::setprecision(4) << d), "3.142");
     }
+
+    template<> template<>
+    void stringize_object::test<3>()
+    {
+        //Tests rely on validity of wstring_to_utf8str()
+        ensure_equals(wstring_to_utf8str(wstringize(c)),    wstring_to_utf8str(L"c"));
+        ensure_equals(wstring_to_utf8str(wstringize(s)),    wstring_to_utf8str(L"17"));
+        ensure_equals(wstring_to_utf8str(wstringize(i)),    wstring_to_utf8str(L"34"));
+        ensure_equals(wstring_to_utf8str(wstringize(l)),    wstring_to_utf8str(L"68"));
+        ensure_equals(wstring_to_utf8str(wstringize(f)),    wstring_to_utf8str(L"3.14159"));
+        ensure_equals(wstring_to_utf8str(wstringize(d)),    wstring_to_utf8str(L"3.14159"));
+        ensure_equals(wstring_to_utf8str(wstringize(abc)),  wstring_to_utf8str(L"abc def"));
+        ensure_equals(wstring_to_utf8str(wstringize(abc)),  wstring_to_utf8str(wstringize(abc.c_str())));
+        ensure_equals(wstring_to_utf8str(wstringize(def)),  wstring_to_utf8str(L"def ghi"));
+ //       ensure_equals(wstring_to_utf8str(wstringize(llsd)), wstring_to_utf8str(L"{'abc':'abc def','d':r3.14159,'i':i34}"));
+    }
 } // namespace tut
diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt
index 12986de8b2c3cf2b94b6c9e90a87ed9eaaeb07fa..ba4e34d92b0e04f3f37eb8962b3914c44fe7b3a9 100755
--- a/indra/llcrashlogger/CMakeLists.txt
+++ b/indra/llcrashlogger/CMakeLists.txt
@@ -23,12 +23,14 @@ include_directories(SYSTEM
 
 set(llcrashlogger_SOURCE_FILES
     llcrashlogger.cpp
+    llcrashlock.cpp
     )
 
 set(llcrashlogger_HEADER_FILES
     CMakeLists.txt
 
     llcrashlogger.h
+    llcrashlock.h
     )
 
 set_source_files_properties(${llcrashlogger_HEADER_FILES}
diff --git a/indra/llcrashlogger/llcrashlock.cpp b/indra/llcrashlogger/llcrashlock.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3d2f944fceec60783595e2ed4577b355d3a5d5f
--- /dev/null
+++ b/indra/llcrashlogger/llcrashlock.cpp
@@ -0,0 +1,209 @@
+/** 
+ * @file llformat.cpp
+ * @date   January 2007
+ * @brief string formatting utility
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * 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.
+ * 
+ * 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.
+ * 
+ * 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 "linden_common.h"
+
+#include "llcrashlock.h"
+#include "lldir.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llnametable.h"
+#include "llframetimer.h"
+#include <boost/filesystem.hpp>  
+#include <string>
+#include <iostream>
+#include <stdio.h>
+
+
+#if LL_WINDOWS   //For windows platform.
+#include <windows.h>
+#include <TlHelp32.h>
+
+namespace {
+	inline DWORD getpid() {
+		return GetCurrentProcessId();
+	}
+}
+
+bool LLCrashLock::isProcessAlive(U32 pid, const std::string& pname)
+{
+	std::wstring wpname;
+	wpname = std::wstring(pname.begin(), pname.end());
+
+	HANDLE snapshot;
+	PROCESSENTRY32 pe32;
+
+	bool matched = false;
+
+	snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (snapshot == INVALID_HANDLE_VALUE)
+	{
+		return false;
+	}
+	else
+	{
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+		if (Process32First(snapshot, &pe32))
+		{
+			do {
+				std::wstring wexecname = pe32.szExeFile; 
+				std::string execname = std::string(wexecname.begin(), wexecname.end());
+				if (!wpname.compare(pe32.szExeFile))
+				{
+					if (pid == (U32)pe32.th32ProcessID)
+					{
+						matched = true;
+						break;
+					}
+				}
+			} while (Process32Next(snapshot, &pe32));
+		}
+	}
+	
+	CloseHandle(snapshot);
+	return matched;
+}
+
+#else   //Everyone Else
+bool LLCrashLock::isProcessAlive(U32 pid, const std::string& pname)
+{
+    //Will boost.process ever become a reality? 
+    std::stringstream cmd;
+    
+    cmd << "pgrep '" << pname << "' | grep '^" << pid << "$'";
+    return (!system(cmd.str().c_str()));
+}
+#endif //Everyone else.
+
+
+LLCrashLock::LLCrashLock() : mCleanUp(true), mWaitingPID(0)
+{
+}
+
+void LLCrashLock::setCleanUp(bool cleanup)
+{
+    mCleanUp = cleanup;  //Allow cleanup to be disabled for debugging.
+}  
+
+LLSD LLCrashLock::getLockFile(std::string filename)
+{
+	LLSD lock_sd = LLSD::emptyMap();
+    
+	llifstream ifile(filename);
+    
+	if (ifile.is_open())
+	{									            
+        LLSDSerialize::fromXML(lock_sd, ifile);
+		ifile.close();
+	}
+
+    return lock_sd;
+}
+
+bool LLCrashLock::putLockFile(std::string filename, const LLSD& data)
+{    
+    bool result = true;
+    llofstream ofile(filename);
+    
+	if (!LLSDSerialize::toXML(data,ofile))
+	{
+        result=false;
+	}
+	ofile.close();
+    return result;
+}
+
+bool LLCrashLock::requestMaster( F32 timeout )
+{
+	if (mMaster.empty())
+	{
+		    mMaster = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+                                            "crash_master.lock");
+	}
+
+    LLSD lock_sd=getLockFile(mMaster);
+    
+    if (lock_sd.has("pid"))
+    {
+        mWaitingPID = lock_sd["pid"].asInteger();
+        if ( isProcessAlive(mWaitingPID, gDirUtilp->getExecutableFilename()) )
+        {
+            mTimer.resetWithExpiry(timeout);
+            return false;
+        }
+    }
+    
+	U32 pid = getpid();
+    lock_sd["pid"] = (LLSD::Integer)pid;
+    return putLockFile(mMaster,lock_sd);
+}
+
+bool LLCrashLock::checkMaster()
+{
+    if (mWaitingPID)
+    {
+        return (!isProcessAlive(mWaitingPID, gDirUtilp->getExecutableFilename()));
+    }
+    return  false;
+}
+
+bool LLCrashLock::isWaiting()
+{
+    return !mTimer.hasExpired();
+}
+
+void LLCrashLock::releaseMaster()
+{
+    //Yeeeeeeehaw
+    unlink(mMaster.c_str());
+}
+
+LLSD LLCrashLock::getProcessList()
+{
+    if (mDumpTable.empty())
+	{
+		mDumpTable= gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+			                                    "crash_table.lock");
+	}
+   return getLockFile(mDumpTable);
+}
+
+//static
+bool LLCrashLock::fileExists(std::string filename)
+{
+	return boost::filesystem::exists(filename.c_str());
+}
+
+void LLCrashLock::cleanupProcess(std::string proc_dir)
+{
+    boost::filesystem::remove_all(proc_dir);
+}
+
+bool LLCrashLock::putProcessList(const LLSD& proc_sd)
+{
+    return putLockFile(mDumpTable,proc_sd);
+}
diff --git a/indra/llcrashlogger/llcrashlock.h b/indra/llcrashlogger/llcrashlock.h
new file mode 100644
index 0000000000000000000000000000000000000000..cde183272f6e9a3a918ae08a4b2c49cdb54713f3
--- /dev/null
+++ b/indra/llcrashlogger/llcrashlock.h
@@ -0,0 +1,73 @@
+/** 
+ * @file llpidlock.h
+ * @brief Maintainence of disk locking files for crash reporting
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * 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.
+ * 
+ * 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.
+ * 
+ * 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$
+ */
+
+#ifndef LL_CRASHLOCK_H
+#define LL_CRASHLOCK_H
+
+#include "llframetimer.h"
+
+class LLSD;
+
+#if !LL_WINDOWS	//For non-windows platforms.
+#include <signal.h>
+#endif
+
+//Crash reporter will now be kicked off by the viewer but otherwise
+//run independent of the viewer.
+
+class LLCrashLock
+{
+public:
+    LLCrashLock();
+    bool requestMaster( F32 timeout=300.0); //Wait until timeout for master lock.
+    bool checkMaster();                     //True if available.  False if not.
+    void releaseMaster( );           //Release master lockfile.
+    bool isLockPresent(std::string filename); //Check if lockfile exists.
+    bool isProcessAlive(U32 pid, const std::string& pname);               //Check if pid is alive.
+    bool isWaiting();                           //Waiting for master lock to be released.
+    LLSD getProcessList();                      //Get next process pid/dir pairs
+    void cleanupProcess(std::string proc_dir);               //Remove from list, clean up working dir.
+    bool putProcessList(const LLSD& processlist); //Write pid/dir pairs back to disk.
+	static bool fileExists(std::string filename);
+    
+
+    //getters
+    S32 getPID();
+
+    //setters
+    void setCleanUp(bool cleanup=true);
+    void setSaveName(std::string savename);
+private:
+    LLSD getLockFile(std::string filename);
+    bool putLockFile(std::string filename, const LLSD& data);
+    bool mCleanUp;
+    std::string mMaster;
+    std::string mDumpTable;
+    U32 mWaitingPID;            //The process we're waiting on if any.
+    LLFrameTimer mTimer;
+};
+
+#endif // LL_CRASHLOCK_H
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index aa66ceb4ecce28bbcab64fc6b497a1e7db2e84b0..38858a1a9110d29c5cf830d6e9422a8f8ce29f0b 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -23,12 +23,14 @@
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */
+
 #include <cstdio>
 #include <cstdlib>
 #include <sstream>
 #include <map>
 
 #include "llcrashlogger.h"
+#include "llcrashlock.h"
 #include "linden_common.h"
 #include "llstring.h"
 #include "indra_constants.h"	// CRASH_BEHAVIOR_...
@@ -43,7 +45,7 @@
 #include "llhttpclient.h"
 #include "llsdserialize.h"
 #include "llproxy.h"
-
+ 
 LLPumpIO* gServicePump = NULL;
 BOOL gBreak = false;
 BOOL gSent = false;
@@ -61,7 +63,7 @@ class LLCrashLoggerResponder : public LLHTTPClient::Responder
 	}
 
 	virtual void result(const LLSD& content)
-	{	
+	{
 		gBreak = true;
 		gSent = true;
 	}
@@ -74,14 +76,11 @@ LLCrashLogger::LLCrashLogger() :
 	mSentCrashLogs(false),
 	mCrashHost("")
 {
-	// Set up generic error handling
-	setupErrorHandling();
 }
 
 LLCrashLogger::~LLCrashLogger()
 {
-	delete gServicePump;
-	gServicePump = NULL;
+
 }
 
 // TRIM_SIZE must remain larger than LINE_SEARCH_SIZE.
@@ -138,19 +137,67 @@ std::string getStartupStateFromLog(std::string& sllog)
 	return startup_state;
 }
 
-void LLCrashLogger::gatherFiles()
+bool LLCrashLogger::readDebugFromXML(LLSD& dest, const std::string& filename )
 {
-	updateApplication("Gathering logs...");
-
-	// Figure out the filename of the debug log
-	std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
-	std::ifstream debug_log_file(db_file_name.c_str());
-
+    std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,filename);
+    std::ifstream debug_log_file(db_file_name.c_str());
+    
 	// Look for it in the debug_info.log file
 	if (debug_log_file.is_open())
 	{
-		LLSDSerialize::fromXML(mDebugLog, debug_log_file);
+		LLSDSerialize::fromXML(dest, debug_log_file);
+        debug_log_file.close();
+        return true;
+    }
+    return false;
+}
+
+void LLCrashLogger::mergeLogs( LLSD src_sd )
+{
+    LLSD::map_iterator iter = src_sd.beginMap();
+	LLSD::map_iterator end = src_sd.endMap();
+	for( ; iter != end; ++iter)
+    {
+        mDebugLog[iter->first] = iter->second;
+    }
+}
+
+bool LLCrashLogger::readMinidump(std::string minidump_path)
+{
+	size_t length=0;
 
+	std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary);
+	if(minidump_stream.is_open())
+	{
+		minidump_stream.seekg(0, std::ios::end);
+		length = (size_t)minidump_stream.tellg();
+		minidump_stream.seekg(0, std::ios::beg);
+		
+		LLSD::Binary data;
+		data.resize(length);
+		
+		minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length);
+		minidump_stream.close();
+		
+		mCrashInfo["Minidump"] = data;
+	}
+	return (length>0?true:false);
+}
+
+void LLCrashLogger::gatherFiles()
+{
+	updateApplication("Gathering logs...");
+
+    LLSD static_sd;
+    LLSD dynamic_sd;
+    
+    bool has_logs = readDebugFromXML( static_sd, "static_debug_info.log" );
+    has_logs |= readDebugFromXML( dynamic_sd, "dynamic_debug_info.log" );
+    
+    if ( has_logs )
+    {
+        mDebugLog = static_sd;
+        mergeLogs(dynamic_sd);
 		mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean();
 
 		mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString();
@@ -171,20 +218,15 @@ void LLCrashLogger::gatherFiles()
 	{
 		// Figure out the filename of the second life log
 		LLCurl::setCAFile(gDirUtilp->getCAFile());
-		mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log");
-		mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
+        
+		mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
+        mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
 	}
 
-	if(mCrashInPreviousExec)
-	{
-		// Restarting after freeze.
-		// Replace the log file ext with .old, since the 
-		// instance that launched this process has overwritten
-		// SecondLife.log
-		std::string log_filename = mFileMap["SecondLifeLog"];
-		log_filename.replace(log_filename.size() - 4, 4, ".old");
-		mFileMap["SecondLifeLog"] = log_filename;
-	}
+    if (!gDirUtilp->fileExists(mFileMap["SecondLifeLog"]) ) //We would prefer to get this from the per-run but here's our fallback.
+    {
+        mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old");
+    }
 
 	gatherPlatformSpecificFiles();
 
@@ -215,7 +257,7 @@ void LLCrashLogger::gatherFiles()
 	mAltCrashHost = "https://login.agni.lindenlab.com:12043/crash/report";
 
 	mCrashInfo["DebugLog"] = mDebugLog;
-	mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log");
+	mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log");
 	
 	updateApplication("Encoding files...");
 
@@ -224,7 +266,7 @@ void LLCrashLogger::gatherFiles()
 		std::ifstream f((*itr).second.c_str());
 		if(!f.is_open())
 		{
-			std::cout << "Can't find file " << (*itr).second << std::endl;
+			LL_INFOS("CRASHREPORT") << "Can't find file " << (*itr).second << LL_ENDL;
 			continue;
 		}
 		std::stringstream s;
@@ -243,32 +285,55 @@ void LLCrashLogger::gatherFiles()
 		mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info));
 	}
 	
+	std::string minidump_path;
 	// Add minidump as binary.
-	std::string minidump_path = mDebugLog["MinidumpPath"];
-	if(minidump_path != "")
+    bool has_minidump = mDebugLog.has("MinidumpPath");
+    
+	if (has_minidump)
 	{
-		std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary);
-		if(minidump_stream.is_open())
-		{
-			minidump_stream.seekg(0, std::ios::end);
-			size_t length = (size_t)minidump_stream.tellg();
-			minidump_stream.seekg(0, std::ios::beg);
-			
-			LLSD::Binary data;
-			data.resize(length);
-			
-			minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length);
-			minidump_stream.close();
-			
-			mCrashInfo["Minidump"] = data;
-		}
+		minidump_path = mDebugLog["MinidumpPath"].asString();
 	}
-	mCrashInfo["DebugLog"].erase("MinidumpPath");
+
+	if (has_minidump)
+	{
+		has_minidump = readMinidump(minidump_path);
+	}
+
+    if (!has_minidump)  //Viewer was probably so hosed it couldn't write remaining data.  Try brute force.
+    {
+       //Look for a filename at least 30 characters long in the dump dir which contains the characters MDMP as the first 4 characters in the file.
+        typedef std::vector<std::string> vec;
+        std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
+        vec file_vec = gDirUtilp->getFilesInDir(pathname);
+        for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
+        {
+            if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) )
+            {
+                std::string fullname = pathname + *iter;
+                std::ifstream fdat( fullname.c_str(), std::ifstream::binary);
+                if (fdat)
+                {
+                    char buf[5];
+                    fdat.read(buf,4);
+                    fdat.close();  
+                    if (!strncmp(buf,"MDMP",4))
+                    {
+                        minidump_path = *iter;
+                        has_minidump = readMinidump(fullname);
+						mDebugLog["MinidumpPath"] = fullname;
+						if (has_minidump) 
+						{
+							break;
+						}
+                    }
+                }
+            }
+        }
+    }
 }
 
 LLSD LLCrashLogger::constructPostData()
 {
-	LLSD ret;
 	return mCrashInfo;
 }
 
@@ -338,39 +403,106 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
 	return gSent;
 }
 
-bool LLCrashLogger::sendCrashLogs()
+bool LLCrashLogger::sendCrashLog(std::string dump_dir)
 {
+    gDirUtilp->setDumpDir( dump_dir );
+    
+    std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+                                                           "SecondLifeCrashReport");
+    std::string report_file = dump_path + ".log";
+   
 	gatherFiles();
-
+    
 	LLSD post_data;
 	post_data = constructPostData();
-
+    
 	updateApplication("Sending reports...");
 
-	std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
-														   "SecondLifeCrashReport");
-	std::string report_file = dump_path + ".log";
-
 	std::ofstream out_file(report_file.c_str());
 	LLSDSerialize::toPrettyXML(post_data, out_file);
 	out_file.close();
-
+    
 	bool sent = false;
-
+    
 	//*TODO: Translate
 	if(mCrashHost != "")
 	{
 		sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5);
 	}
-
+    
 	if(!sent)
 	{
 		sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3, 5);
 	}
-	    
+    
 	mSentCrashLogs = sent;
+    
+	return sent;
+}
 
-	return true;
+bool LLCrashLogger::sendCrashLogs()
+{
+    
+    //pertinent code from below moved into a subroutine.
+    LLSD locks = mKeyMaster.getProcessList();
+    LLSD newlocks = LLSD::emptyArray();
+
+	LLSD opts = getOptionData(PRIORITY_COMMAND_LINE);
+    LLSD rec;
+
+	if ( opts.has("pid") && opts.has("dumpdir") && opts.has("procname") )
+    {
+        rec["pid"]=opts["pid"];
+        rec["dumpdir"]=opts["dumpdir"];
+        rec["procname"]=opts["procname"];
+    }
+	
+    if (locks.isArray())
+    {
+        for (LLSD::array_iterator lock=locks.beginArray();
+             lock !=locks.endArray();
+             ++lock)
+        {
+            if ( (*lock).has("pid") && (*lock).has("dumpdir") && (*lock).has("procname") )
+            {
+                if ( mKeyMaster.isProcessAlive( (*lock)["pid"].asInteger(), (*lock)["procname"].asString() ) )
+                {
+                    newlocks.append(*lock);
+                }
+                else
+                {
+					//TODO:  This is a hack but I didn't want to include boost in another file or retest everything related to lldir 
+                    if (LLCrashLock::fileExists((*lock)["dumpdir"].asString()))
+                    {
+                        //the viewer cleans up the log directory on clean shutdown
+                        //but is ignorant of the locking table. 
+                        if (!sendCrashLog((*lock)["dumpdir"].asString()))
+                        {
+                            newlocks.append(*lock);    //Failed to send log so don't delete it.
+                        }
+                        else
+                        {
+                            //mCrashInfo["DebugLog"].erase("MinidumpPath");
+
+                            mKeyMaster.cleanupProcess((*lock)["dumpdir"].asString());
+                        }
+                    }
+				}
+            }
+            else
+            {
+                llwarns << "Discarding corrupted entry from lock table." << llendl;
+            }
+        }
+    }
+
+    if (rec)
+    {
+        newlocks.append(rec);
+    }
+    
+    mKeyMaster.putProcessList(newlocks);
+    return true;
 }
 
 void LLCrashLogger::updateApplication(const std::string& message)
@@ -395,44 +527,62 @@ bool LLCrashLogger::init()
 	// Rename current log file to ".old"
 	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old");
 	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log");
-	LLFile::rename(log_file.c_str(), old_log_file.c_str());
 
+#if LL_WINDOWS
+	LLAPRFile::remove(old_log_file);
+#endif 
+
+	LLFile::rename(log_file.c_str(), old_log_file.c_str());
+    
 	// Set the log file to crashreport.log
-	LLError::logToFile(log_file);
-	
-	mCrashSettings.declareS32("CrashSubmitBehavior", CRASH_BEHAVIOR_ALWAYS_SEND,
+	LLError::logToFile(log_file);  //NOTE:  Until this line, LL_INFOS LL_WARNS, etc are blown to the ether. 
+
+    // Handle locking
+    bool locked = mKeyMaster.requestMaster();  //Request master locking file.  wait time is defaulted to 300S
+    
+    while (!locked && mKeyMaster.isWaiting())
+    {
+		LL_INFOS("CRASHREPORT") << "Waiting for lock." << LL_ENDL;
+#if LL_WINDOWS
+		Sleep(1000);
+#else
+        sleep(1);
+#endif 
+        locked = mKeyMaster.checkMaster();
+    }
+    
+    if (!locked)
+    {
+        LL_WARNS("CRASHREPORT") << "Unable to get master lock.  Another crash reporter may be hung." << LL_ENDL;
+        return false;
+    }
+
+    mCrashSettings.declareS32("CrashSubmitBehavior", CRASH_BEHAVIOR_ALWAYS_SEND,
 							  "Controls behavior when viewer crashes "
 							  "(0 = ask before sending crash report, "
 							  "1 = always send crash report, "
 							  "2 = never send crash report)");
-
+    
 	// llinfos << "Loading crash behavior setting" << llendl;
 	// mCrashBehavior = loadCrashBehaviorSetting();
-
+    
 	// If user doesn't want to send, bail out
 	if (mCrashBehavior == CRASH_BEHAVIOR_NEVER_SEND)
 	{
 		llinfos << "Crash behavior is never_send, quitting" << llendl;
 		return false;
 	}
-
+    
 	gServicePump = new LLPumpIO(gAPRPoolp);
 	gServicePump->prime(gAPRPoolp);
 	LLHTTPClient::setPump(*gServicePump);
-
-	//If we've opened the crash logger, assume we can delete the marker file if it exists
-	if( gDirUtilp )
-	{
-		std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
-																 "SecondLife.exec_marker");
-		LLAPRFile::remove( marker_file );
-	}
-	
+ 	
 	return true;
 }
 
 // For cleanup code common to all platforms.
 void LLCrashLogger::commonCleanup()
 {
+	LLError::logToFile("");   //close crashreport.log
 	LLProxy::cleanupClass();
 }
diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h
index 1510d7e0b3d33ea4d0acc4e012c496a824da1ac8..78acc63b6a8eafc2d95b8691ea87745ec1c07647 100755
--- a/indra/llcrashlogger/llcrashlogger.h
+++ b/indra/llcrashlogger/llcrashlogger.h
@@ -33,6 +33,7 @@
 #include "llapp.h"
 #include "llsd.h"
 #include "llcontrol.h"
+#include "llcrashlock.h"
 
 class LLCrashLogger : public LLApp
 {
@@ -40,9 +41,13 @@ class LLCrashLogger : public LLApp
 	LLCrashLogger();
 	virtual ~LLCrashLogger();
 	S32 loadCrashBehaviorSetting();
+    bool readDebugFromXML(LLSD& dest, const std::string& filename );
 	void gatherFiles();
+    void mergeLogs( LLSD src_sd );
+
 	virtual void gatherPlatformSpecificFiles() {}
 	bool saveCrashBehaviorSetting(S32 crash_behavior);
+    bool sendCrashLog(std::string dump_dir);
 	bool sendCrashLogs();
 	LLSD constructPostData();
 	virtual void updateApplication(const std::string& message = LLStringUtil::null);
@@ -53,6 +58,8 @@ class LLCrashLogger : public LLApp
 	void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
 	S32 getCrashBehavior() { return mCrashBehavior; }
 	bool runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout);
+	bool readMinidump(std::string minidump_path);
+
 protected:
 	S32 mCrashBehavior;
 	BOOL mCrashInPreviousExec;
@@ -65,6 +72,7 @@ class LLCrashLogger : public LLApp
 	std::string mAltCrashHost;
 	LLSD mDebugLog;
 	bool mSentCrashLogs;
+    LLCrashLock mKeyMaster;
 };
 
 #endif //LLCRASHLOGGER_H
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 6899e9a44a3ff73702813ac8efdaa5fa0f8eec60..0d65c3f8c338ef0e761cb72a7392072515c4163d 100755
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -42,6 +42,7 @@
 
 #include "lldiriterator.h"
 #include "stringize.h"
+#include <boost/filesystem.hpp>
 #include <boost/foreach.hpp>
 #include <boost/range/begin.hpp>
 #include <boost/range/end.hpp>
@@ -76,6 +77,7 @@ const char
 	*LLDir::SKINBASE = "";
 
 static const char* const empty = "";
+std::string LLDir::sDumpDir = "";
 
 LLDir::LLDir()
 :	mAppName(""),
@@ -99,7 +101,32 @@ LLDir::~LLDir()
 {
 }
 
-
+std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
+{
+    //Returns a vector of fullpath filenames.
+    
+    boost::filesystem::path p (dirname);
+    std::vector<std::string> v;
+    
+    if (exists(p))
+    {
+        if (is_directory(p))
+        {
+            boost::filesystem::directory_iterator end_iter;
+            for (boost::filesystem::directory_iterator dir_itr(p);
+                 dir_itr != end_iter;
+                 ++dir_itr)
+            {
+                if (boost::filesystem::is_regular_file(dir_itr->status()))
+                {
+                    v.push_back(dir_itr->path().filename().string());
+                }
+            }
+        }
+    }
+    return v;
+}   
+            
 S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
 {
 	S32 count = 0;
@@ -158,6 +185,34 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
 	return count;
 }
 
+U32 LLDir::deleteDirAndContents(const std::string& dir_name)
+{
+    //Removes the directory and its contents.  Returns number of files deleted.
+	
+	U32 num_deleted = 0;
+
+	try
+	{
+	   boost::filesystem::path dir_path(dir_name);
+	   if (boost::filesystem::exists (dir_path))
+	   {
+	      if (!boost::filesystem::is_empty (dir_path))
+		  {   // Directory has content
+		     num_deleted = boost::filesystem::remove_all (dir_path);
+		  }
+		  else
+		  {   // Directory is empty
+		     boost::filesystem::remove (dir_path);
+		  }
+	   }
+	}
+	catch (boost::filesystem::filesystem_error &er)
+	{ 
+		llwarns << "Failed to delete " << dir_name << " with error " << er.code().message() << llendl;
+	} 
+	return num_deleted;
+}
+
 const std::string LLDir::findFile(const std::string &filename, 
 						   const std::string& searchPath1, 
 						   const std::string& searchPath2, 
@@ -244,11 +299,36 @@ const std::string &LLDir::getLindenUserDir() const
 	return mLindenUserDir;
 }
 
-const std::string &LLDir::getChatLogsDir() const
+const std::string& LLDir::getChatLogsDir() const
 {
 	return mChatLogsDir;
 }
 
+void LLDir::setDumpDir( const std::string& path )
+{
+    LLDir::sDumpDir = path;
+    if (! sDumpDir.empty() && sDumpDir.rbegin() == mDirDelimiter.rbegin() )
+    {
+        sDumpDir.erase(sDumpDir.size() -1);
+    }
+}
+
+const std::string &LLDir::getDumpDir() const
+{
+    if (sDumpDir.empty() )
+    {
+        LLUUID uid;
+        uid.generate();
+        
+        sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")
+                    + "dump-" + uid.asString();
+
+        dir_exists_or_crash(sDumpDir);  
+    }
+
+	return LLDir::sDumpDir;
+}
+
 const std::string &LLDir::getPerAccountChatLogsDir() const
 {
 	return mPerAccountChatLogsDir;
@@ -420,6 +500,10 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
 		prefix = getCacheDir();
 		break;
 		
+    case LL_PATH_DUMP:
+        prefix=getDumpDir();
+        break;
+            
 	case LL_PATH_USER_SETTINGS:
 		prefix = add(getOSUserAppDir(), "user_settings");
 		break;
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index e02bf552aadccfd7b38dc83f26346cf7a18f04bb..b219c6e29fb00e6b4a197fc495e2bdc0876d576a 100755
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -53,6 +53,7 @@ typedef enum ELLPath
 	LL_PATH_EXECUTABLE = 16,
 	LL_PATH_DEFAULT_SKIN = 17,
 	LL_PATH_FONTS = 18,
+    LL_PATH_DUMP = 19,
 	LL_PATH_LAST
 } ELLPath;
 
@@ -71,7 +72,8 @@ class LLDir
 		const std::string& app_read_only_data_dir = "") = 0;
 
 	virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
-
+    U32 deleteDirAndContents(const std::string& dir_name);
+    std::vector<std::string> getFilesInDir(const std::string &dirname);
 // pure virtual functions
 	virtual std::string getCurPath() = 0;
 	virtual bool fileExists(const std::string &filename) const = 0;
@@ -92,6 +94,7 @@ class LLDir
 	const std::string &getOSUserAppDir() const;	// Location of the os-specific user app dir
 	const std::string &getLindenUserDir() const;	// Location of the Linden user dir.
 	const std::string &getChatLogsDir() const;	// Location of the chat logs dir.
+	const std::string &getDumpDir() const;	// Location of the per-run dump dir.
 	const std::string &getPerAccountChatLogsDir() const;	// Location of the per account chat logs dir.
 	const std::string &getTempDir() const;			// Common temporary directory
 	const std::string  getCacheDir(bool get_default = false) const;	// Location of the cache.
@@ -179,6 +182,8 @@ class LLDir
 	// For producing safe download file names from potentially unsafe ones
 	static std::string getScrubbedFileName(const std::string uncleanFileName);
 	static std::string getForbiddenFileChars();
+    void setDumpDir( const std::string& path );
+
 
 	virtual void setChatLogsDir(const std::string &path);		// Set the chat logs dir to this user's dir
 	virtual void setPerAccountChatLogsDir(const std::string &username);		// Set the per user chat log directory.
@@ -245,6 +250,7 @@ class LLDir
 	std::vector<std::string> mSearchSkinDirs;
 	std::string mLanguage;              // Current viewer language
 	std::string mLLPluginDir;			// Location for plugins and plugin shell
+    static std::string sDumpDir;            // Per-run crash report subdir of log directory.
 	std::string mUserName;				// Current user name
 };
 
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index e00596cdb5c2869e30a6aa041aa750164a5f9456..2f47ab35071a1d891739c717e59726e05ee32bc4 100755
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -134,7 +134,7 @@ LLDir_Mac::LLDir_Mac()
 		
 		{
             mOSCacheDir = *cachedir;
-            //Aura TODO:  This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife.  Last dir level could go away.
+            //TODO:  This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife.  Last dir level could go away.
             CreateDirectory(mOSCacheDir, secondLifeString, NULL);
 		}
 		
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 0424f2379e04888139456af47fbb30e1620677fd..b5fd3673a60629d330a7becb9e3e42da9ece559c 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -274,3 +274,8 @@ void LLPidLock::setSaveName(std::string savename)
 { 
 	LLPidLockFile::instance().mSaveName=savename; 
 }
+
+S32 LLPidLock::getPID()
+{
+    return (S32)getpid();
+}
diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h
index d3295f4911054dd7d8974a20b9400f2488b7f712..334f26bb294b13a4bd2c30e16ad581bd97a9c693 100755
--- a/indra/llvfs/llpidlock.h
+++ b/indra/llvfs/llpidlock.h
@@ -39,21 +39,22 @@ namespace LLPidLock
 {
     void initClass(); // { (void) LLPidLockFile::instance(); }
 
-	bool requestLock( LLNameTable<void *> *name_table=NULL, bool autosave=TRUE,
-					  bool force_immediate=FALSE, F32 timeout=300.0);
-	bool checkLock(); 
-	void releaseLock(); 
-	bool isClean(); 
-
-	//getters
-	LLNameTable<void *> * getNameTable(); 
-	bool getAutosave(); 
-	bool getClean(); 
-	std::string getSaveName(); 
-
-	//setters
-	void setClean(bool clean); 
-	void setSaveName(std::string savename); 
+    bool requestLock( LLNameTable<void *> *name_table=NULL, bool autosave=TRUE,
+                     bool force_immediate=FALSE, F32 timeout=300.0);
+    bool checkLock();
+    void releaseLock();
+    bool isClean();
+
+    //getters
+    LLNameTable<void *> * getNameTable();
+    bool getAutosave();
+    bool getClean();
+    std::string getSaveName();
+    S32 getPID();
+
+    //setters
+    void setClean(bool clean);
+    void setSaveName(std::string savename);
 };
 
 #endif // LL_PIDLOCK_H
diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp
index c5f660ca6ed42c8525b4e7cb590c097642ce3340..351009814d9b72630f3cbf76c1934111c178ea90 100755
--- a/indra/mac_crash_logger/llcrashloggermac.cpp
+++ b/indra/mac_crash_logger/llcrashloggermac.cpp
@@ -89,5 +89,6 @@ bool LLCrashLoggerMac::mainLoop()
 bool LLCrashLoggerMac::cleanup()
 {
 	commonCleanup();
+    mKeyMaster.releaseMaster();
 	return true;
 }
diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp
index 6add74556fc72eb3d957d9d9940cee3b9e0dbed7..2c83f3439dd3c5ab862c932df3b5863f12b7ed00 100755
--- a/indra/mac_crash_logger/mac_crash_logger.cpp
+++ b/indra/mac_crash_logger/mac_crash_logger.cpp
@@ -27,6 +27,7 @@
 #include "linden_common.h"
 #include "llcrashloggermac.h"
 #include "indra_constants.h"
+#include "llpidlock.h"
 
 #include <iostream>
     
@@ -35,6 +36,14 @@ int main(int argc, char **argv)
 	LLCrashLoggerMac app;
 	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;
@@ -44,9 +53,7 @@ int main(int argc, char **argv)
     {
 //        return NSApplicationMain(argc, (const char **)argv);
     }
-
 	app.mainLoop();
-
 	app.cleanup();
 
 	llinfos << "Crash reporter finished normally." << llendl;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 17e340d136f14cbd3a584b24b462281df3b55fc7..0bf0152b303a9f6c2f18160e26fc3833a879bdb0 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1282,6 +1282,8 @@ set_source_files_properties(
 
 if (DARWIN)
   LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
+  LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.mm)
+  LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.h)
   LIST(APPEND viewer_SOURCE_FILES llfilepicker_mac.mm)
   LIST(APPEND viewer_HEADER_FILES llfilepicker_mac.h)
 
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index aaf18d29482f17f2ad2793f0104a27740b190352..897e56be0b6911813b9baecd20ea8de49244b917 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.5
+3.7.6
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e3c89f1a5f4b7144411fb06d4b7890fe41688f75..63d31824e478a86144c4abc71b1b051980ab9a60 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -691,9 +691,26 @@ LLAppViewer::LLAppViewer() :
 		llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
 	}
 
-	setupErrorHandling();
+    mDumpPath ="";
+
+	// Need to do this initialization before we do anything else, since anything
+	// that touches files should really go through the lldir API
+	gDirUtilp->initAppDirs("SecondLife");
+	//
+	// IMPORTANT! Do NOT put anything that will write
+	// into the log files during normal startup until AFTER
+	// we run the "program crashed last time" error handler below.
+	//
 	sInstance = this;
+
 	gLoggedInTime.stop();
+
+	initLoggingAndGetLastDuration();
+	
+	processMarkerFiles();
+	//
+	// OK to write stuff to logs now, we've now crash reported if necessary
+	//
 	
 	LLLoginInstance::instance().setUpdaterService(mUpdater.get());
 	LLLoginInstance::instance().setPlatformInfo(gPlatform, getOSInfo().getOSVersionString());
@@ -707,9 +724,9 @@ LLAppViewer::~LLAppViewer()
 	LLLoginInstance::instance().setUpdaterService(0);
 	
 	destroyMainloopTimeout();
-
+    
 	// If we got to this destructor somehow, the app didn't hang.
-	removeMarkerFile();
+	removeMarkerFiles();
 }
 
 class LLUITranslationBridge : public LLTranslationBridge
@@ -723,13 +740,11 @@ class LLUITranslationBridge : public LLTranslationBridge
 
 bool LLAppViewer::init()
 {	
+	setupErrorHandling();
+
 	//
 	// Start of the application
 	//
-	// IMPORTANT! Do NOT put anything that will write
-	// into the log files during normal startup until AFTER
-	// we run the "program crashed last time" error handler below.
-	//
 	LLFastTimer::reset();
 	
 	
@@ -747,21 +762,15 @@ bool LLAppViewer::init()
 	//initialize particle index pool
 	LLVOPartGroup::initClass();
 
-	// Need to do this initialization before we do anything else, since anything
-	// that touches files should really go through the lldir API
-	gDirUtilp->initAppDirs("SecondLife");
 	// set skin search path to default, will be overridden later
 	// this allows simple skinned file lookups to work
 	gDirUtilp->setSkinFolder("default", "en");
 
-	initLoggingAndGetLastDuration();
-	
-	processMarkerFiles();
+//	initLoggingAndGetLastDuration();
 	
 	//
 	// OK to write stuff to logs now, we've now crash reported if necessary
 	//
-	
 	init_default_trans_args();
 	
 	if (!initConfiguration())
@@ -774,11 +783,13 @@ bool LLAppViewer::init()
 	LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
 
 	LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")*1024*1024) ;
-
-	// write Google Breakpad minidump files to our log directory
-	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-	logdir += gDirUtilp->getDirDelimiter();
+	// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
+	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
+	mDumpPath = logdir;
 	setMiniDumpDir(logdir);
+	logdir += gDirUtilp->getDirDelimiter();
+    setDebugFileNames(logdir);
+
 
 	// Although initLoggingAndGetLastDuration() is the right place to mess with
 	// setFatalFunction(), we can't query gSavedSettings until after
@@ -1763,7 +1774,7 @@ bool LLAppViewer::cleanup()
 		gAudiop->setStreamingAudioImpl(NULL);
 
 		// shut down the audio subsystem
-        gAudiop->shutdown();
+		gAudiop->shutdown();
 
 		delete gAudiop;
 		gAudiop = NULL;
@@ -1930,8 +1941,6 @@ bool LLAppViewer::cleanup()
 		llinfos << "Purging all cache files on exit" << llendflush;
 		gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
 	}
-
-	removeMarkerFile(); // Any crashes from here on we'll just have to ignore
 	
 	writeDebugInfo();
 
@@ -2088,10 +2097,14 @@ bool LLAppViewer::cleanup()
 
 	ll_close_fail_log();
 
+	removeMarkerFiles();
+	
 	MEM_TRACK_RELEASE
 
     llinfos << "Goodbye!" << llendflush;
 
+    removeDumpDir();
+
 	// return 0;
 	return true;
 }
@@ -2181,7 +2194,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	// Get name of the log file
 	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
 							     "SecondLife.log");
-	/*
+ 	/*
 	 * Before touching any log files, compute the duration of the last run
 	 * by comparing the ctime of the previous start marker file with the ctime
 	 * of the last log file.
@@ -2576,17 +2589,17 @@ bool LLAppViewer::initConfiguration()
                 {
 					llwarns << "Failed --set " << name << ": setting name unknown." << llendl;
                 }
-                }
             }
         }
+    }
 
     if  (clp.hasOption("logevents")) {
-	LLViewerEventRecorder::instance().setEventLoggingOn();
+		LLViewerEventRecorder::instance().setEventLoggingOn();
     }
 
 	std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
 	if(! CmdLineChannel.empty())
-	{
+    {
 		LLVersionInfo::resetChannel(CmdLineChannel);
 	}
 
@@ -2598,16 +2611,16 @@ bool LLAppViewer::initConfiguration()
 		LLFastTimer::sLog = TRUE;
 		LLFastTimer::sLogName = std::string("performance");		
 	}
-
+	
 	std::string test_name(gSavedSettings.getString("LogMetrics"));
 	if (! test_name.empty())
-	{
+ 	{
  		LLFastTimer::sMetricLog = TRUE ;
 		// '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
 		// In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
 		llinfos << "'--logmetrics' argument : " << test_name << llendl;
 			LLFastTimer::sLogName = test_name;
- 	}
+		}
 
 	if (clp.hasOption("graphicslevel"))
 	{
@@ -2616,14 +2629,14 @@ bool LLAppViewer::initConfiguration()
 		// that value for validity.
 		U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");
 		if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel))
-		{
+        {
 			// graphicslevel is valid: save it and engage it later. Capture
 			// the requested value separately from the settings variable
 			// because, if this is the first run, LLViewerWindow's constructor
 			// will call LLFeatureManager::applyRecommendedSettings(), which
 			// overwrites this settings variable!
 			mForceGraphicsLevel = graphicslevel;
-		}
+        }
 	}
 
 	LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
@@ -2657,11 +2670,11 @@ bool LLAppViewer::initConfiguration()
 	LLSLURL start_slurl;
 	std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));
 	if(! CmdLineLoginLocation.empty())
-	{
+    {
 		start_slurl = CmdLineLoginLocation;
 		LLStartUp::setStartSLURL(start_slurl);
 		if(start_slurl.getType() == LLSLURL::LOCATION) 
-	{
+		{  
 			LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
 		}
 	}
@@ -2675,11 +2688,11 @@ bool LLAppViewer::initConfiguration()
 		(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
 	{
 		if (sendURLToOtherInstance(start_slurl.getSLURLString()))
-		{  
+		{
 			// successfully handed off URL to existing instance, exit
 			return false;
 		}
-	}
+    }
 
 	const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
 	if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
@@ -2706,38 +2719,6 @@ bool LLAppViewer::initConfiguration()
 
     mYieldTime = gSavedSettings.getS32("YieldTime");
 
-	// Read skin/branding settings if specified.
-	//if (! gDirUtilp->getSkinDir().empty() )
-	//{
-	//	std::string skin_def_file = gDirUtilp->findSkinnedFilename("skin.xml");
-	//	LLXmlTree skin_def_tree;
-
-	//	if (!skin_def_tree.parseFile(skin_def_file))
-	//	{
-	//		llerrs << "Failed to parse skin definition." << llendl;
-	//	}
-
-	//}
-
-#if LL_DARWIN
-
-#if __ppc__
-	// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
-	// Only test PowerPC - all Intel Macs have SSE.
-	if(!gSysCPU.hasAltivec())
-	{
-		std::ostringstream msg;
-		msg << LLTrans::getString("MBRequiresAltiVec");
-		OSMessageBox(
-			msg.str(),
-			LLStringUtil::null,
-			OSMB_OK);
-		removeMarkerFile();
-		return false;
-	}
-#endif
-	
-#endif // LL_DARWIN
 
 	// Display splash screen.  Must be after above check for previous
 	// crash as this dialog is always frontmost.
@@ -2808,10 +2789,6 @@ bool LLAppViewer::initConfiguration()
 			disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
 		}
 	}
-	else
-	{
-		checkForCrash();
-	}
 
    	// NextLoginLocation is set from the command line option
 	std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
@@ -2996,26 +2973,26 @@ namespace {
 		{
 			LL_WARNS("UpdaterService") << "no info url supplied - defaulting to hard coded release notes pattern" << LL_ENDL;
 
-			// truncate version at the rightmost '.' 
-			std::string version_short(data["version"]);
-			size_t short_length = version_short.rfind('.');
-			if (short_length != std::string::npos)
-			{
-				version_short.resize(short_length);
-			}
+		// truncate version at the rightmost '.' 
+		std::string version_short(data["version"]);
+		size_t short_length = version_short.rfind('.');
+		if (short_length != std::string::npos)
+		{
+			version_short.resize(short_length);
+		}
 
-			LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
-			relnotes_url.setArg("[VERSION_SHORT]", version_short);
+		LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
+		relnotes_url.setArg("[VERSION_SHORT]", version_short);
 
-			// *TODO thread the update service's response through to this point
-			std::string const & channel = LLVersionInfo::getChannel();
-			boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
+		// *TODO thread the update service's response through to this point
+		std::string const & channel = LLVersionInfo::getChannel();
+		boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
 
-			relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
-			relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
+		relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
+		relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
 			substitutions["INFO_URL"] = relnotes_url.getString();
 		}
-		
+
 		LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
 	}
 
@@ -3115,19 +3092,6 @@ void LLAppViewer::initUpdater()
     updater_pump.listen("notify_update", &notify_update);
 }
 
-void LLAppViewer::checkForCrash(void)
-{
-#if LL_SEND_CRASH_REPORTS
-	if (gLastExecEvent == LAST_EXEC_FROZE)
-    {
-        llinfos << "Last execution froze, sending a crash report." << llendl;
-            
-		bool report_freeze = true;
-		handleCrashReporting(report_freeze);
-    }
-#endif // LL_SEND_CRASH_REPORTS    
-}
-
 //
 // This function decides whether the client machine meets the minimum requirements to
 // run in a maximized window, per the consensus of davep, boa and nyx on 3/30/2011.
@@ -3204,7 +3168,7 @@ bool LLAppViewer::initWindow()
 		LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
 		gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
 	}
-
+			
 	// Set this flag in case we crash while initializing GL
 	gSavedSettings.setBOOL("RenderInitError", TRUE);
 	gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
@@ -3254,12 +3218,21 @@ bool LLAppViewer::initWindow()
 	return true;
 }
 
-void LLAppViewer::writeDebugInfo()
+void LLAppViewer::writeDebugInfo(bool isStatic)
 {
-	std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
-	llinfos << "Opening debug file " << debug_filename << llendl;
-	llofstream out_file(debug_filename);
-	LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
+    //Try to do the minimum when writing data during a crash.
+    std::string* debug_filename;
+    debug_filename = ( isStatic
+        ? getStaticDebugFile()
+        : getDynamicDebugFile() );
+    
+	llinfos << "Opening debug file " << *debug_filename << llendl;
+	llofstream out_file(*debug_filename);
+    
+    isStatic ?  LLSDSerialize::toPrettyXML(gDebugInfo, out_file)
+             :  LLSDSerialize::toPrettyXML(gDebugInfo["Dynamic"], out_file);
+    
+        
 	out_file.close();
 }
 
@@ -3439,7 +3412,6 @@ std::string LLAppViewer::getViewerInfoString() const
 	return support.str();
 }
 
-
 void LLAppViewer::cleanupSavedSettings()
 {
 	gSavedSettings.setBOOL("MouseSun", FALSE);
@@ -3488,7 +3460,16 @@ void LLAppViewer::removeCacheFiles(const std::string& file_mask)
 
 void LLAppViewer::writeSystemInfo()
 {
-	gDebugInfo["SLLog"] = LLError::logFileName();
+    
+    if (! gDebugInfo.has("Dynamic") )
+        gDebugInfo["Dynamic"] = LLSD::emptyMap();
+    
+#if LL_WINDOWS
+	gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
+#else
+    //Not ideal but sufficient for good reporting.
+    gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old");  //LLError::logFileName();
+#endif
 
 	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
 	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
@@ -3552,9 +3533,55 @@ void LLAppViewer::writeSystemInfo()
 	LL_INFOS("SystemInfo") << "OS: " << getOSInfo().getOSStringSimple() << LL_ENDL;
 	LL_INFOS("SystemInfo") << "OS info: " << getOSInfo() << LL_ENDL;
 
+    gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
+	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
+	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
+	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
+	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
+    gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
+    
 	writeDebugInfo(); // Save out debug_info.log early, in case of crash.
 }
 
+#ifdef LL_WINDOWS
+//For whatever reason, in Windows when using OOP server for breakpad, the callback to get the 
+//name of the dump file is not getting triggered by the breakpad library.   Unfortunately they 
+//also didn't see fit to provide a simple query request across the pipe to get this name either.
+//Since we are putting our output in a runtime generated directory and we know the header data in
+//the dump format, we can however use the following hack to identify our file. 
+// TODO make this a member function.
+void getFileList()
+{
+	std::stringstream filenames;
+
+	typedef std::vector<std::string> vec;
+	std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
+	vec file_vec = gDirUtilp->getFilesInDir(pathname);
+	for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
+	{
+		filenames << *iter << " ";
+		if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) )
+		{
+			std::string fullname = pathname + *iter;
+			std::ifstream fdat( fullname.c_str(), std::ifstream::binary);
+			if (fdat)
+			{
+				char buf[5];
+				fdat.read(buf,4);
+				fdat.close();
+				if (!strncmp(buf,"MDMP",4))
+				{
+					gDebugInfo["Dynamic"]["MinidumpPath"] = fullname;
+					break;
+				}
+			}
+		}
+	}
+	filenames << std::endl;
+	gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str();
+}
+#endif
+
 void LLAppViewer::handleViewerCrash()
 {
 	llinfos << "Handle viewer crash entry." << llendl;
@@ -3590,73 +3617,51 @@ void LLAppViewer::handleViewerCrash()
 	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
 	if(crashHostUrl != "")
 	{
-		gDebugInfo["CrashHostUrl"] = crashHostUrl;
+		gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl;
 	}
 	
-	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
-	//to check against no matter what
-	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
-
-	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
-	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
-	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
-	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
-
 	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
 	if ( parcel && parcel->getMusicURL()[0])
 	{
-		gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
+		gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL();
 	}	
 	if ( parcel && parcel->getMediaURL()[0])
 	{
-		gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
+		gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL();
 	}
 	
 	
-	gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
-	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
-	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
-	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
-	gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
-	gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
-	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
-	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
-	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
-
-	char *minidump_file = pApp->getMiniDumpFilename();
-	if(minidump_file && minidump_file[0] != 0)
-	{
-		gDebugInfo["MinidumpPath"] = minidump_file;
-	}
+	gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
+	gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
 	
 	if(gLogoutInProgress)
 	{
-		gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
+		gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
 	}
 	else
 	{
-		gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
+		gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
 	}
 
 	if(gAgent.getRegion())
 	{
-		gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
-		gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
+		gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
+		gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
 		
 		const LLVector3& loc = gAgent.getPositionAgent();
-		gDebugInfo["CurrentLocationX"] = loc.mV[0];
-		gDebugInfo["CurrentLocationY"] = loc.mV[1];
-		gDebugInfo["CurrentLocationZ"] = loc.mV[2];
+		gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0];
+		gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1];
+		gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2];
 	}
 
 	if(LLAppViewer::instance()->mMainloopTimeout)
 	{
-		gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
+		gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
 	}
 	
 	// The crash is being handled here so set this value to false.
 	// Otherwise the crash logger will think this crash was a freeze.
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
+	gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
     
 	//Write out the crash status file
 	//Use marker file style setup, as that's the simplest, especially since
@@ -3664,9 +3669,9 @@ void LLAppViewer::handleViewerCrash()
 	if (gDirUtilp)
 	{
 		std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
-																	 gLLErrorActivated
-																	 ? LLERROR_MARKER_FILE_NAME
-																	 : ERROR_MARKER_FILE_NAME);
+																			gLLErrorActivated
+																			? LLERROR_MARKER_FILE_NAME
+																			: ERROR_MARKER_FILE_NAME);
 		LLAPRFile crash_marker_file ;
 		crash_marker_file.open(crash_marker_file_name, LL_APR_WB);
 		if (crash_marker_file.getFileHandle())
@@ -3677,17 +3682,35 @@ void LLAppViewer::handleViewerCrash()
 		else
 		{
 			LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL;
-		}		
+		}
 	}
 	else
 	{
 		LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL;
 	}		
 	
+#ifdef LL_WINDOWS
+	Sleep(200);
+#endif 
+
+	char *minidump_file = pApp->getMiniDumpFilename();
+
+	if(minidump_file && minidump_file[0] != 0)
+	{
+		gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file;
+	}
+#ifdef LL_WINDOWS
+	else
+	{
+		getFileList();
+	}
+#endif
+    gDebugInfo["Dynamic"]["CrashType"]="crash";
+	
 	if (gMessageSystem && gDirUtilp)
 	{
 		std::string filename;
-		filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log");
 		llofstream file(filename, llofstream::binary);
 		if(file.good())
 		{
@@ -3703,29 +3726,10 @@ void LLAppViewer::handleViewerCrash()
 		gMessageSystem->stopLogging();
 	}
 
-	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo);
+	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
 
 	// Close the debug file
-	pApp->writeDebugInfo();
-
-	LLError::logToFile("");
-
-	// Remove the marker file, since otherwise we'll spawn a process that'll keep it locked
-	if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
-	{
-		pApp->removeMarkerFile(true);
-	}
-	else
-	{
-		pApp->removeMarkerFile(false);
-	}
-	
-#if LL_SEND_CRASH_REPORTS
-	// Call to pure virtual, handled by platform specific llappviewer instance.
-	pApp->handleCrashReporting(); 
-#endif
-    
-	return;
+	pApp->writeDebugInfo(false);  //false answers the isStatic question with the least overhead.
 }
 
 // static
@@ -3816,7 +3820,7 @@ void LLAppViewer::processMarkerFiles()
 		}
 
 		if (mSecondInstance)
-	{
+		{
 			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL;
 		}
 		else if (marker_is_same_version)
@@ -3830,7 +3834,7 @@ void LLAppViewer::processMarkerFiles()
 		{
 			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL;
 		}
-	}    
+	}
 	else // marker did not exist... last exec (if any) did not freeze
 	{
 		// Create the marker file for this execution & lock it; it will be deleted on a clean exit
@@ -3884,12 +3888,12 @@ void LLAppViewer::processMarkerFiles()
 			{
 				gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
 				LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
-		}
-		else
-		{
+			}
+			else
+			{
 				gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
 				LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL;
-		}
+			}
 		}
 		else
 		{
@@ -3902,54 +3906,51 @@ void LLAppViewer::processMarkerFiles()
 	if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
 	{
 		if (markerIsSameVersion(error_marker_file))
-	{
-			if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
 		{
+			if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
+			{
 				gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
 				LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
-		}
-		else
-		{
+			}
+			else
+			{
 				gLastExecEvent = LAST_EXEC_OTHER_CRASH;
 				LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+			}
 		}
-	}
-	else
-	{
+		else
+		{
 			LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
 		}
 		LLAPRFile::remove(error_marker_file);
 	}
 }
 
-void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
+void LLAppViewer::removeMarkerFiles()
 {
 	if (!mSecondInstance)
 	{		
-		LL_DEBUGS("MarkerFile") << (leave_logout_marker?"leave":"remove") <<" logout" << LL_ENDL;
-	if (mMarkerFile.getFileHandle())
-	{
-			LL_DEBUGS("MarkerFile") << "removing exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
+		if (mMarkerFile.getFileHandle())
+		{
 			mMarkerFile.close() ;
-		LLAPRFile::remove( mMarkerFileName );
-	}
-	else
-	{
+			LLAPRFile::remove( mMarkerFileName );
+			LL_DEBUGS("MarkerFile") << "removed exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
+		}
+		else
+		{
 			LL_WARNS("MarkerFile") << "marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
-	}
-	if (!leave_logout_marker)
-	{
+ 		}
+
 		if (mLogoutMarkerFile.getFileHandle())
 		{
-				LL_DEBUGS("MarkerFile") << "removing logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
 			mLogoutMarkerFile.close();
+			LLAPRFile::remove( mLogoutMarkerFileName );
+			LL_DEBUGS("MarkerFile") << "removed logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
 		}
 		else
 		{
-				LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
+			LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
 		}
-		LLAPRFile::remove( mLogoutMarkerFileName );
-	}
 	}
 	else
 	{
@@ -3957,6 +3958,14 @@ void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
 	}
 }
 
+void LLAppViewer::removeDumpDir()
+{
+    //Call this routine only on clean exit.  Crash reporter will clean up
+    //its locking table for us.
+    std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
+    gDirUtilp->deleteDirAndContents(dump_dir);
+}
+
 void LLAppViewer::forceQuit()
 { 
 	LLApp::setQuitting(); 
@@ -3974,7 +3983,7 @@ void LLAppViewer::fastQuit(S32 error_code)
 	// figure out the error code
 	S32 final_error_code = error_code ? error_code : (S32)isError();
 	// this isn't a crash	
-	removeMarkerFile();
+	removeMarkerFiles();
 	// get outta here
 	_exit(final_error_code);	
 }
@@ -5152,20 +5161,26 @@ void LLAppViewer::sendLogoutRequest()
 	{
 		//Set internal status variables and marker files before actually starting the logout process
 		gLogoutInProgress = TRUE;
-		mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
-		
-		LLAPRFile outfile ;
-		mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
-		if (mLogoutMarkerFile.getFileHandle())
+		if (!mSecondInstance)
 		{
-			LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
-			recordMarkerVersion(outfile);
+			mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
+		
+			mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
+			if (mLogoutMarkerFile.getFileHandle())
+			{
+				LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
+				recordMarkerVersion(mLogoutMarkerFile);
+			}
+			else
+			{
+				LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
+			}		
 		}
 		else
 		{
-			LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
-		}		
-
+			LL_INFOS("MarkerFile") << "Did not logout marker file because this is a second instance" << LL_ENDL;
+		}
+		
 		LLMessageSystem* msg = gMessageSystem;
 		msg->newMessageFast(_PREHASH_LogoutRequest);
 		msg->nextBlockFast(_PREHASH_AgentData);
@@ -5643,7 +5658,7 @@ void LLAppViewer::launchUpdater()
 	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
 
 	//Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
-	LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
+	LLAppViewer::instance()->removeMarkerFiles(); // In case updater fails
 
 	// *NOTE:Mani The updater is spawned as the last thing before the WinMain exit.
 	// see LLAppViewerWin32.cpp
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 05326c2bafe70785c2c2c48e626dc84b717463f4..cbaa7bc4c2719036693c81cb55078ba80ab496be 100755
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -46,7 +46,6 @@ class LLViewerJoystick;
 
 extern LLFastTimer::DeclareTimer FTM_FRAME;
 
-
 class LLAppViewer : public LLApp
 {
 public:
@@ -82,7 +81,7 @@ class LLAppViewer : public LLApp
     bool quitRequested() { return mQuitRequested; }
     bool logoutRequestSent() { return mLogoutRequestSent; }
 
-	void writeDebugInfo();
+	void writeDebugInfo(bool isStatic=true);
 
 	const LLOSInfo& getOSInfo() const { return mSysOSInfo; }
 
@@ -95,7 +94,7 @@ class LLAppViewer : public LLApp
 
 	virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.
 	                                     // return false if the error trap needed restoration.
-	virtual void handleCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report?
+	virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report?
 	static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon.
     void checkForCrash();
     
@@ -123,8 +122,9 @@ class LLAppViewer : public LLApp
     void loadNameCache();
     void saveNameCache();
 
-	void removeMarkerFile(bool leave_logout_marker = false);
+	void removeMarkerFiles();
 	
+	void removeDumpDir();
     // LLAppViewer testing helpers.
     // *NOTE: These will potentially crash the viewer. Only for debugging.
     virtual void forceErrorLLError();
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index b16bb573e1b483ffd6958312bd16581397effb7f..11fcf0018e3442b8df9484da325d818ec5a106b9 100755
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -58,12 +58,15 @@ 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.
-	LLAppViewer::handleViewerCrash();
+    long *null_ptr;
+    null_ptr = 0;
+    *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
 	// we've probably been killed-off before now, but...
 	gOldTerminateHandler(); // call old terminate() handler
 }
@@ -127,7 +130,17 @@ bool LLAppViewerLinux::init()
 	// really early in app startup!
 	if (!g_thread_supported ()) g_thread_init (NULL);
 	
-	return LLAppViewer::init();
+	bool success = LLAppViewer::init();
+
+#if LL_SEND_CRASH_REPORTS
+    if (success)
+    {
+        LLAppViewer* pApp = LLAppViewer::instance();
+        pApp->initCrashReporting();
+    }
+#endif
+
+	return success;
 }
 
 bool LLAppViewerLinux::restoreErrorTrap()
@@ -319,7 +332,7 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
 }
 #endif // LL_DBUS_ENABLED
 
-void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)
+void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
 {
 	std::string cmd =gDirUtilp->getExecutableDir();
 	cmd += gDirUtilp->getDirDelimiter();
@@ -331,69 +344,52 @@ void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)
 # error Unknown platform
 #endif
 
-	if(reportFreeze)
-	{
-		char* const cmdargv[] =
-			{(char*)cmd.c_str(),
-			 (char*)"-previous",
-			 NULL};
-
-		fflush(NULL); // flush all buffers before the child inherits them
-		pid_t pid = fork();
-		if (pid == 0)
-		{ // child
-			execv(cmd.c_str(), cmdargv);		/* Flawfinder: Ignore */
-			llwarns << "execv failure when trying to start " << cmd << llendl;
-			_exit(1); // avoid atexit()
-		} else {
-			if (pid > 0)
-			{
-				// wait for child proc to die
-				int childExitStatus;
-				waitpid(pid, &childExitStatus, 0);
-			} else {
-				llwarns << "fork failure." << llendl;
-			}
-		}
-	}
+    std::stringstream pid_str;
+    pid_str <<  LLApp::getPid();
+    std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
+    std::string appname = gDirUtilp->getExecutableFilename();
+	// launch the actual crash logger
+	const char * cmdargv[] =
+		{cmd.c_str(),
+		 "-user",
+		 (char*)LLGridManager::getInstance()->getGridId().c_str(),
+		 "-name",
+		 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
+		 "-pid", 
+		 pid_str.str().c_str(),
+		 "-dumpdir",
+		 logdir.c_str(),
+		 "-procname",
+		 appname.c_str(),
+		 NULL};
+	fflush(NULL);
+
+	pid_t pid = fork();
+	if (pid == 0)
+	{ // child
+		execv(cmd.c_str(), (char* const*) cmdargv);		/* Flawfinder: ignore */
+		llwarns << "execv failure when trying to start " << cmd << llendl;
+		_exit(1); // avoid atexit()
+	} 
 	else
 	{
-		// launch the actual crash logger
-		const char * cmdargv[] =
-			{cmd.c_str(),
-			 "-user",
-			 (char*)LLGridManager::getInstance()->getGridId().c_str(),
-			 "-name",
-			 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
-			 NULL};
-		fflush(NULL);
-		pid_t pid = fork();
-		if (pid == 0)
-		{ // child
-			execv(cmd.c_str(), (char* const*) cmdargv);		/* Flawfinder: ignore */
-			llwarns << "execv failure when trying to start " << cmd << llendl;
-			_exit(1); // avoid atexit()
+		if (pid > 0)
+		{
+			// DO NOT wait for child proc to die; we want
+			// the logger to outlive us while we quit to
+			// free up the screen/keyboard/etc.
+			////int childExitStatus;
+			////waitpid(pid, &childExitStatus, 0);
 		} 
 		else
 		{
-			if (pid > 0)
-			{
-				// DO NOT wait for child proc to die; we want
-				// the logger to outlive us while we quit to
-				// free up the screen/keyboard/etc.
-				////int childExitStatus;
-				////waitpid(pid, &childExitStatus, 0);
-			} 
-			else
-			{
-				llwarns << "fork failure." << llendl;
-			}
+			llwarns << "fork failure." << llendl;
 		}
-		// Sometimes signals don't seem to quit the viewer.  Also, we may
-		// have been called explicitly instead of from a signal handler.
-		// Make sure we exit so as to not totally confuse the user.
-		_exit(1); // avoid atexit(), else we may re-crash in dtors.
 	}
+	// Sometimes signals don't seem to quit the viewer.  Also, we may
+	// have been called explicitly instead of from a signal handler.
+	// Make sure we exit so as to not totally confuse the user.
+	//_exit(1); // avoid atexit(), else we may re-crash in dtors.
 }
 
 bool LLAppViewerLinux::beingDebugged()
diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h
index fb77600c10e7c02ca2ff45f9f8fa57f0eeba107c..0289c43043f2a906ce2b2f24c02be4223270fe93 100755
--- a/indra/newview/llappviewerlinux.h
+++ b/indra/newview/llappviewerlinux.h
@@ -61,7 +61,7 @@ class LLAppViewerLinux : public LLAppViewer
 	virtual bool beingDebugged();
 	
 	virtual bool restoreErrorTrap();
-	virtual void handleCrashReporting(bool reportFreeze);
+	virtual void initCrashReporting(bool reportFreeze);
 
 	virtual void initLoggingAndGetLastDuration();
 	virtual bool initParseCommandLine(LLCommandLineParser& clp);
diff --git a/indra/newview/llappviewermacosx-objc.h b/indra/newview/llappviewermacosx-objc.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6dcec8e34e7161b3d9424f12cf75e29e3059095
--- /dev/null
+++ b/indra/newview/llappviewermacosx-objc.h
@@ -0,0 +1,36 @@
+/**
+ * @file llappviewermacosx.h
+ * @brief The LLAppViewerMacOSX class declaration
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * 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.
+ * 
+ * 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.
+ * 
+ * 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$
+ */ 
+
+#ifndef LL_LLAPPVIEWERMACOSX_OBJC_H
+#define LL_LLAPPVIEWERMACOSX_OBJC_H
+
+#include <string>
+#include <vector>
+
+//Why?  Because BOOL
+void launchApplication(const std::string* app_name, const std::vector<std::string>* args);
+
+#endif // LL_LLAPPVIEWERMACOSX_OBJC_H
diff --git a/indra/newview/llappviewermacosx-objc.mm b/indra/newview/llappviewermacosx-objc.mm
new file mode 100644
index 0000000000000000000000000000000000000000..17301847e8bc08ff5e76d11f3db97fe8af20cd60
--- /dev/null
+++ b/indra/newview/llappviewermacosx-objc.mm
@@ -0,0 +1,73 @@
+/**
+ * @file llappviewermacosx-objc.mm
+ * @brief Functions related to LLAppViewerMacOSX that must be expressed in obj-c
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * 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.
+ * 
+ * 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.
+ * 
+ * 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$
+ */ 
+
+#if !defined LL_DARWIN
+	#error "Use only with Mac OS X"
+#endif
+
+#import <Cocoa/Cocoa.h>
+#include <iostream>
+
+#include "llappviewermacosx-objc.h"
+
+void launchApplication(const std::string* app_name, const std::vector<std::string>* args)
+{
+
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    
+	if (app_name->empty()) return;
+
+	NSMutableString* app_name_ns = [NSMutableString stringWithString:[[NSBundle mainBundle] resourcePath]];	//Path to resource dir
+	[app_name_ns appendFormat:@"/%@", [NSString stringWithCString:app_name->c_str() 
+								encoding:[NSString defaultCStringEncoding]]];
+
+	NSMutableArray *args_ns = nil;
+	args_ns = [[NSMutableArray alloc] init];
+
+	for (int i=0; i < args->size(); ++i)
+	{
+        NSLog(@"Adding string %s", (*args)[i].c_str());
+		[args_ns addObject:
+			[NSString stringWithCString:(*args)[i].c_str()
+						encoding:[NSString defaultCStringEncoding]]];
+	}
+
+    NSTask *task = [[NSTask alloc] init];
+    NSBundle *bundle = [NSBundle bundleWithPath:[[NSWorkspace sharedWorkspace] fullPathForApplication:app_name_ns]];
+    [task setLaunchPath:[bundle executablePath]];
+    [task setArguments:args_ns];
+    [task launch];
+    
+//	NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
+//	NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:app_name_ns]];
+//
+//	NSError *error = nil;
+//	[workspace launchApplicationAtURL:url options:0 configuration:[NSDictionary dictionaryWithObject:args_ns forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
+	//TODO Handle error
+    
+    [pool release];
+	return;
+}
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 2723f0b90d5affe705c33d0b66863cdbc6587c31..c6d45cf4d6d9f33fb08a5580a417c300f995f494 100755
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -32,6 +32,9 @@
 
 #define LL_CARBON_CRASH_HANDLER 1
 
+#include "llwindowmacosx.h"
+#include "llappviewermacosx-objc.h"
+
 #include "llappviewermacosx.h"
 #include "llwindowmacosx-objc.h"
 #include "llcommandlineparser.h"
@@ -45,6 +48,9 @@
 #ifdef LL_CARBON_CRASH_HANDLER
 #include <Carbon/Carbon.h>
 #endif
+#include <vector>
+#include <exception>
+
 #include "lldir.h"
 #include <signal.h>
 #include <CoreAudio/CoreAudio.h>	// for systemwide mute
@@ -56,7 +62,6 @@ namespace
 	// They are not used immediately by the app.
 	int gArgC;
 	char** gArgV;
-	bool sCrashReporterIsRunning = false;
 	LLAppViewerMacOSX* gViewerAppPtr;
 #ifdef LL_CARBON_CRASH_HANDLER
 	OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
@@ -68,6 +73,20 @@ namespace
 		return(result);
 	}
 #endif
+    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
 }
 
 bool initViewer()
@@ -83,19 +102,21 @@ bool initViewer()
 		<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
 		<< llendl;
 	}
-	
+
 	gViewerAppPtr = new LLAppViewerMacOSX();
-	
+
+    // install unexpected exception handler
+	gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
+
 	gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
-	
-	
+
 	
 	bool ok = gViewerAppPtr->init();
 	if(!ok)
 	{
 		llwarns << "Application init failed." << llendl;
 	}
-	
+
 	return ok;
 }
 
@@ -121,7 +142,8 @@ void cleanupViewer()
 {
 	if(!LLApp::isError())
 	{
-		gViewerAppPtr->cleanup();
+        if (gViewerAppPtr)
+            gViewerAppPtr->cleanup();
 	}
 	
 	delete gViewerAppPtr;
@@ -146,7 +168,17 @@ LLAppViewerMacOSX::~LLAppViewerMacOSX()
 
 bool LLAppViewerMacOSX::init()
 {
-	return LLAppViewer::init();
+	bool success = LLAppViewer::init();
+    
+#if LL_SEND_CRASH_REPORTS
+    if (success)
+    {
+        LLAppViewer* pApp = LLAppViewer::instance();
+        pApp->initCrashReporting();
+    }
+#endif
+    
+    return success;
 }
 
 // MacOSX may add and addition command line arguement for the process serial number.
@@ -263,132 +295,17 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
 	return reset_count == 0;
 }
 
-#ifdef LL_CARBON_CRASH_HANDLER
-static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
-								   EventRef inEvent,
-								   void* inUserData)
+void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
 {
-    ProcessSerialNumber psn;
-	
-    GetEventParameter(inEvent,
-					  kEventParamProcessID,
-					  typeProcessSerialNumber,
-					  NULL,
-					  sizeof(psn),
-					  NULL,
-					  &psn);
-	
-    if( GetEventKind(inEvent) == kEventAppTerminated )
-	{
-		Boolean matching_psn = FALSE;
-		OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn);
-		if(os_result >= 0 && matching_psn)
-		{
-			sCrashReporterIsRunning = false;
-			QuitApplicationEventLoop();
-		}
-    }
-    return noErr;
-}
-#endif
-
-void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
-{
-#ifdef LL_CARBON_CRASH_HANDLER
-	// This used to use fork&exec, but is switched to LSOpenApplication to
-	// Make sure the crash reporter launches in front of the SL window.
-	
-	std::string command_str;
-	//command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app";
-	command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger";
-	
-	CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)command_str.c_str(), strlen(command_str.c_str()), FALSE);
-	
-	// FSRef apparently isn't deprecated.
-	// There's other funcitonality that depends on it existing as well that isn't deprecated.
-	// There doesn't seem to be much to directly verify what the status of FSRef is, outside of some documentation pointing at FSRef being valid, and other documentation pointing to everything in Files.h being deprecated.
-	// We'll assume it isn't for now, since all non-deprecated functions that use it seem to assume similar.
-	
-	FSRef appRef;
-	Boolean pathstatus = CFURLGetFSRef(urlRef, &appRef);
-	
-	OSStatus os_result = noErr;
-	
-	if(pathstatus == true)
-	{
-		LSApplicationParameters appParams;
-		memset(&appParams, 0, sizeof(appParams));
-	 	appParams.version = 0;
-		appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic;
-		
-		appParams.application = &appRef;
-		
-		if(reportFreeze)
-		{
-			// Make sure freeze reporting launches the crash logger synchronously, lest
-			// Log files get changed by SL while the logger is running.
-			
-			// *NOTE:Mani A better way - make a copy of the data that the crash reporter will send
-			// and let SL go about its business. This way makes the mac work like windows and linux
-			// and is the smallest patch for the issue.
-			sCrashReporterIsRunning = false;
-			ProcessSerialNumber o_psn;
-			
-			static EventHandlerRef sCarbonEventsRef = NULL;
-			static const EventTypeSpec kEvents[] =
-			{
-				{ kEventClassApplication, kEventAppTerminated }
-			};
-			
-			// Install the handler to detect crash logger termination
-			InstallEventHandler(GetApplicationEventTarget(),
-								(EventHandlerUPP) CarbonEventHandler,
-								GetEventTypeCount(kEvents),
-								kEvents,
-								&o_psn,
-								&sCarbonEventsRef
-								);
-			
-			// Remove, temporarily the quit handler - which has *crash* behavior before
-			// the mainloop gets running!
-			AERemoveEventHandler(kCoreEventClass,
-								 kAEQuitApplication,
-								 NewAEEventHandlerUPP(AEQuitHandler),
-								 false);
-			
-			// Launch the crash reporter.
-			os_result = LSOpenApplication(&appParams, &o_psn);
-			
-			if(os_result >= 0)
-			{
-				sCrashReporterIsRunning = true;
-			}
-			
-			while(sCrashReporterIsRunning)
-			{
-				RunApplicationEventLoop();
-			}
-			
-			// Re-install the apps quit handler.
-			AEInstallEventHandler(kCoreEventClass,
-								  kAEQuitApplication,
-								  NewAEEventHandlerUPP(AEQuitHandler),
-								  0,
-								  false);
-			
-			// Remove the crash reporter quit handler.
-			RemoveEventHandler(sCarbonEventsRef);
-		}
-		else
-		{
-			appParams.flags |= kLSLaunchAsync;
-			clear_signals();
-			
-			ProcessSerialNumber o_psn;
-			os_result = LSOpenApplication(&appParams, &o_psn);
-		}
-	}
-#endif
+	std::string command_str = "mac-crash-logger.app";
+    
+    std::stringstream pid_str;
+    pid_str <<  LLApp::getPid();
+    std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
+    std::string appname = gDirUtilp->getExecutableFilename();
+    std::string str[] = { "-pid", pid_str.str(), "-dumpdir", logdir, "-procname", appname.c_str() };
+    std::vector< std::string > args( str, str + ( sizeof ( str ) /  sizeof ( std::string ) ) );
+    launchApplication(&command_str, &args);
 }
 
 std::string LLAppViewerMacOSX::generateSerialNumber()
diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h
index 25053da5e8dd10e825e93c671e628a2225328468..ebb41a495cee21f9df2d160079a920fea27d92c7 100755
--- a/indra/newview/llappviewermacosx.h
+++ b/indra/newview/llappviewermacosx.h
@@ -48,7 +48,7 @@ class LLAppViewerMacOSX : public LLAppViewer
 
 protected:
 	virtual bool restoreErrorTrap();
-	virtual void handleCrashReporting(bool reportFreeze); 
+	virtual void initCrashReporting(bool reportFreeze);
 
 	std::string generateSerialNumber();
 	virtual bool initParseCommandLine(LLCommandLineParser& clp);
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
old mode 100755
new mode 100644
index 2764025d75d82c99a4799ff0e8272c26fe451a07..d9a0eb25e490a3f5d6f68d731fcfd6869de351f3
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -65,6 +65,33 @@
 #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*/)
+{
+	llwarns << "Hit last ditch-effort attempt to catch crash." << llendl;
+	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
@@ -236,8 +263,14 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
 
 	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);
@@ -488,7 +521,19 @@ bool LLAppViewerWin32::init()
 	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()
@@ -627,26 +672,53 @@ bool LLAppViewerWin32::restoreErrorTrap()
 	//return LLWinDebug::checkExceptionHandler();
 }
 
-void LLAppViewerWin32::handleCrashReporting(bool reportFreeze)
+void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
 {
 	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)
-	{
-		// 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
-	{
-		_spawnl(_P_NOWAIT, exe_path.c_str(), arg_str, NULL);
-	}
+	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=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()'
+	{
+        LL_WARNS("CrashReport Launch") << "CreateProcess failed " << GetLastError() << LL_ENDL;
+        return;
+    }
 }
 
 //virtual
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
old mode 100755
new mode 100644
index 386bddd495dbd9326de6a4803dcd6811f1330746..fb37df1a2f0df52ec54d5ff6fca324579ec6b417
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -50,7 +50,7 @@ class LLAppViewerWin32 : public LLAppViewer
 	virtual bool initParseCommandLine(LLCommandLineParser& clp);
 
 	virtual bool restoreErrorTrap();
-	virtual void handleCrashReporting(bool reportFreeze); 
+	virtual void initCrashReporting(bool reportFreeze); 
 
 	virtual bool sendURLToOtherInstance(const std::string& url);
 
diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp
index 5ecdd1191813b9f202988479a57bd9694d19a86f..54c7b4c37dcfd1a0c6b28e360c115021353c1ea1 100755
--- a/indra/newview/llfloaterspellchecksettings.cpp
+++ b/indra/newview/llfloaterspellchecksettings.cpp
@@ -307,12 +307,12 @@ void LLFloaterSpellCheckerImport::onBtnOK()
 	else
 	{
 		std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic";
-		if ( copyFile( dict_dic, settings_dic ) )
+		if ( LLFile::copy( dict_dic, settings_dic ) )
 		{
 			if (gDirUtilp->fileExists(dict_aff))
 			{
 				std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff";
-				if (copyFile( dict_aff, settings_aff ))
+				if ( LLFile::copy( dict_aff, settings_aff ))
 				{
 					imported = true;
 				}
@@ -385,37 +385,6 @@ void LLFloaterSpellCheckerImport::onBtnOK()
 	closeFloater(false);
 }
 
-bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::string to)
-{
-	bool copied = false;
-	LLFILE* in = LLFile::fopen(from, "rb");		/* Flawfinder: ignore */	 	
-	if (in)	 	
-	{	 	
-		LLFILE* out = LLFile::fopen(to, "wb");		/* Flawfinder: ignore */
-		if (out)
-		{
-			char buf[16384];		/* Flawfinder: ignore */ 	
-			size_t readbytes;
-			bool write_ok = true;
-			while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
-			{
-				if (fwrite(buf, 1, readbytes, out) != readbytes)
-				{
-					LL_WARNS("SpellCheck") << "Short write" << LL_ENDL; 
-					write_ok = false;
-				}
-			}
-			if ( write_ok )
-			{
-				copied = true;
-			}
-			fclose(out);
-		}
-	}
-	fclose(in);
-	return copied;
-}
-
 std::string LLFloaterSpellCheckerImport::parseXcuFile(const std::string& file_path) const
 {
 	LLXMLNodePtr xml_root;
diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h
index eded3a9133d0c8b751c34d3af31c878c80289ce3..de59d83f24243b1d1bd86b695248353a0c299b8c 100755
--- a/indra/newview/llfloaterspellchecksettings.h
+++ b/indra/newview/llfloaterspellchecksettings.h
@@ -58,7 +58,6 @@ class LLFloaterSpellCheckerImport : public LLFloater
 	void onBtnBrowse();
 	void onBtnCancel();
 	void onBtnOK();
-	bool copyFile(const std::string from, const std::string to);
 	std::string parseXcuFile(const std::string& file_path) const;
 
 	std::string mDictionaryDir;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d5f8a1e46ea1a2fde693107de2c7f55178db46f0..d4b3fcf28a1a70da8feca145ca53720e1834036b 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -3510,7 +3510,8 @@ bool process_login_success_response()
 	{
 		success = true;
 	}
-
+    LLAppViewer* pApp = LLAppViewer::instance();
+	pApp->writeDebugInfo();     //Write our static data now that we have username, session_id, etc.
 	return success;
 }
 
diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt
index 3c9a4b97569706542b4a056b99df2d3238fb1bdb..c6070020db4973d22e92d40adb2a7486327ce868 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
old mode 100755
new mode 100644
index 36d988ead750b3d9689068d5592b9e380af5df39..9fd66d542113ceaa5cdf6b9bbd0aed0a12a27927
--- a/indra/win_crash_logger/llcrashloggerwindows.cpp
+++ b/indra/win_crash_logger/llcrashloggerwindows.cpp
@@ -42,6 +42,11 @@
 #include "lldxhardware.h"
 #include "lldir.h"
 #include "llsdserialize.h"
+#include "llsdutil.h"
+#include "stringize.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 +69,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,10 +246,178 @@ 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;
+	UINT_PTR timerID = SetTimer(NULL, NULL, 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;
+	int retries = 0;
+	const int max_retries = 60;
+
+	LL_DEBUGS("CRASHREPORT") << "Entering processing loop for OOP server" << LL_ENDL;
+
+	LLSD options = getOptionData( LLApp::PRIORITY_COMMAND_LINE );
+
+	MSG msg;
+	
+	bool result;
+
+    while (1) 
+	{
+		result = getMessageWithTimeout(&msg, millisecs);
+		if ( result ) 
+		{
+			TranslateMessage(&msg);
+			DispatchMessage(&msg);
+		}
+
+		if ( retries < max_retries )  //Wait up to 1 minute for the viewer to say hello.
+		{
+			if (mClientsConnected == 0) 
+			{
+				LL_DEBUGS("CRASHREPORT") << "Waiting for client to connect." << LL_ENDL;
+				++retries;
+			}
+			else
+			{
+				LL_INFOS("CRASHREPORT") << "Client has connected!" << LL_ENDL;
+				retries = max_retries;
+			}
+		} 
+		else 
+		{
+			if (mClientsConnected == 0)
+			{
+				break;
+			}
+			if (!mKeyMaster.isProcessAlive(mPID, mProcName) )
+			{
+				break;
+			}
+		} 
+    }
+    
+    llinfos << "session ending.." << llendl;
+    
+    std::string per_run_dir = options["dumpdir"].asString();
+	std::string per_run_file = per_run_dir + "\\SecondLife.log";
+    std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log");
+
+	if (gDirUtilp->fileExists(per_run_dir))  
+	{
+		LL_INFOS ("CRASHREPORT") << "Copying " << log_file << " to " << per_run_file << llendl;
+	    LLFile::copy(log_file, per_run_file);
+	}
+	return 0;
+}
+
+
+void LLCrashLoggerWindows::OnClientConnected(void* context,
+				const google_breakpad::ClientInfo* client_info) 
+{
+	sInstance->mClientsConnected++;
+	LL_INFOS("CRASHREPORT") << "Client connected. pid = " << client_info->pid() << " total clients " << sInstance->mClientsConnected << LL_ENDL;
+}
+
+void LLCrashLoggerWindows::OnClientExited(void* context,
+		const google_breakpad::ClientInfo* client_info) 
+{
+	sInstance->mClientsConnected--;
+	LL_INFOS("CRASHREPORT") << "Client disconnected. pid = " << client_info->pid() << " total clients " << sInstance->mClientsConnected << LL_ENDL;
+}
+
+
+void LLCrashLoggerWindows::OnClientDumpRequest(void* context,
+	const google_breakpad::ClientInfo* client_info,
+	const std::wstring* file_path) 
+{
+	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();
+}
+
+
+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();
+
+	//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. 
+	std::wstring wpipe_name;
+	wpipe_name = mCrashReportPipeStr + std::wstring(wstringize(mPID));
+
+	std::wstring wdump_path( wstringize(dump_path) );
+		
+	//Pipe naming conventions:  http://msdn.microsoft.com/en-us/library/aa365783%28v=vs.85%29.aspx
+	mCrashHandler = new CrashGenerationServer( wpipe_name,
+		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;
+	}
+
+	LL_INFOS("CRASHREPORT") << "Initialized OOP server with pipe named " << stringize(wpipe_name) << LL_ENDL;
+	return true;
 }
 
 bool LLCrashLoggerWindows::init(void)
@@ -251,10 +425,12 @@ bool LLCrashLoggerWindows::init(void)
 	bool ok = LLCrashLogger::init();
 	if(!ok) return false;
 
+	initCrashServer();
+
 	/*
 	mbstowcs( gProductName, mProductName.c_str(), LL_ARRAY_SIZE(gProductName) );
 	gProductName[ LL_ARRY_SIZE(gProductName) - 1 ] = 0;
-	swprintf(gProductName, L"Second Life");
+	swprintf(gProductName, L"Second Life"); 
 	*/
 
 	llinfos << "Loading dialogs" << llendl;
@@ -291,18 +467,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 +545,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
old mode 100755
new mode 100644
index 5c45a998b328f221015280171bffcdb1fe26ea84..1812e2737ec1d2f01a6fb46641ba8360a2bd8598
--- 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 8e916ae437e796391d2723485a9334b3875d2554..79b85147250050fe27d1202477b0cb1e1d821349 100755
--- a/indra/win_crash_logger/win_crash_logger.cpp
+++ b/indra/win_crash_logger/win_crash_logger.cpp
@@ -34,18 +34,24 @@ int APIENTRY WinMain(HINSTANCE hInstance,
                      LPSTR     lpCmdLine,
                      int       nCmdShow)
 {
-	llinfos << "Starting crash reporter." << llendl;
-
+	llinfos << "Starting crash reporter with args" << &lpCmdLine << 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;
 	}
 
+	app.processingLoop();
 	app.mainLoop();
 	app.cleanup();
 	llinfos << "Crash reporter finished normally." << llendl;