From c0731c1c05cafe508c91c5f583301234ba3b8403 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 17 Jan 2012 18:55:42 -0500
Subject: [PATCH] Add log message if LLProcessLauncher child fails to execv().
 On a Posix platform (vfork()/execv() implementation), if for any reason the
 execv() failed (e.g. executable not on PATH), the viewer would never know,
 nor the user: the vfork() child produced no output, and terminated with rc 0!
 Add logging, make child terminate with nonzero rc. Remove pointless
 addArgument(const char*) overload: this does nothing for you that the
 compiler won't do implicitly. In llupdateinstaller.cpp, remove pointless
 c_str() call in addArgument() arg: we were starting with a std::string, then
 extracting its c_str(), only to construct a whole new std::string from it!

---
 indra/llcommon/llprocesslauncher.cpp          | 20 ++++++++++---------
 indra/llcommon/llprocesslauncher.h            |  4 +++-
 .../updater/llupdateinstaller.cpp             |  2 +-
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index 10950181fd3..25d64e9e282 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -73,11 +73,6 @@ void LLProcessLauncher::addArgument(const std::string &arg)
 	mLaunchArguments.push_back(arg);
 }
 
-void LLProcessLauncher::addArgument(const char *arg)
-{
-	mLaunchArguments.push_back(std::string(arg));
-}
-
 #if LL_WINDOWS
 
 int LLProcessLauncher::launch(void)
@@ -262,12 +257,19 @@ int LLProcessLauncher::launch(void)
 	if(id == 0)
 	{
 		// child process
-		
 		::execv(mExecutable.c_str(), (char * const *)fake_argv);
-		
+
 		// If we reach this point, the exec failed.
-		// Use _exit() instead of exit() per the vfork man page.
-		_exit(0);
+        LL_WARNS("LLProcessLauncher") << "failed to launch: ";
+        for (const char * const * ai = fake_argv; *ai; ++ai)
+        {
+            LL_CONT << *ai << ' ';
+        }
+        LL_CONT << LL_ENDL;
+		// Use _exit() instead of exit() per the vfork man page. Exit with a
+		// distinctive rc: someday soon we'll be able to retrieve it, and it
+		// would be nice to be able to tell that the child process failed!
+		_exit(249);
 	}
 
 	// parent process
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
index 954c2491472..1daa980c58f 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -28,6 +28,7 @@
 #define LL_LLPROCESSLAUNCHER_H
 
 #if LL_WINDOWS
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 
@@ -51,7 +52,6 @@ class LL_COMMON_API LLProcessLauncher
 
 	void clearArguments();
 	void addArgument(const std::string &arg);
-	void addArgument(const char *arg);
 		
 	int launch(void);
 	bool isRunning(void);
@@ -66,10 +66,12 @@ class LL_COMMON_API LLProcessLauncher
 	void orphan(void);	
 	
 	// This needs to be called periodically on Mac/Linux to clean up zombie processes.
+	// (However, as of 2012-01-12 there are no such calls in the viewer code base. :-P )
 	static void reap(void);
 	
 	// Accessors for platform-specific process ID
 #if LL_WINDOWS
+	// (Windows flavor unused as of 2012-01-12)
 	HANDLE getProcessHandle() { return mProcessHandle; };
 #else
 	pid_t getProcessID() { return mProcessID; };
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index c7b70c2de8e..84f23b3accb 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -81,7 +81,7 @@ int ll_install_update(std::string const & script,
 	LLProcessLauncher launcher;
 	launcher.setExecutable(actualScriptPath);
 	launcher.addArgument(updatePath);
-	launcher.addArgument(ll_install_failed_marker_path().c_str());
+	launcher.addArgument(ll_install_failed_marker_path());
 	launcher.addArgument(boost::lexical_cast<std::string>(required));
 	int result = launcher.launch();
 	launcher.orphan();
-- 
GitLab