Browse Source

Switch from vfork/exec to posix_spawn after clang static analyzer run

Bart van Strien 11 years ago
parent
commit
ce385ec27a
1 changed files with 24 additions and 30 deletions
  1. 24 30
      src/modules/system/System.cpp

+ 24 - 30
src/modules/system/System.cpp

@@ -25,8 +25,9 @@
 #if defined(LOVE_MACOSX)
 #include <CoreServices/CoreServices.h>
 #elif defined(LOVE_LINUX)
-#include <stdlib.h>
-#include <unistd.h>
+#include <spawn.h>
+//#include <stdlib.h>
+//#include <unistd.h>
 #include <sys/wait.h>
 #elif defined(LOVE_WINDOWS)
 #include "common/utf8.h"
@@ -53,12 +54,17 @@ std::string System::getOS() const
 #endif
 }
 
+extern "C"
+{
+	extern char **environ; // The environment, always available
+}
+
 bool System::openURL(const std::string &url) const
 {
-	bool success = false;
 
 #if defined(LOVE_MACOSX)
 
+	bool success = false;
 	// We could be lazy and use system("open " + url), but this is safer.
 	CFURLRef cfurl = CFURLCreateWithBytes(nullptr,
 	                                      (const UInt8 *) url.c_str(),
@@ -68,34 +74,24 @@ bool System::openURL(const std::string &url) const
 
 	success = LSOpenCFURLRef(cfurl, nullptr) == noErr;
 	CFRelease(cfurl);
+	return success;
 
 #elif defined(LOVE_LINUX)
 
-	// Spawn a child process, which we'll replace with xdg-open.
-	pid_t pid = vfork();
-
-	if (pid == 0) // Child process.
-	{
-		// Replace the child process with xdg-open and pass in the URL.
-		execlp("xdg-open", "xdg-open", url.c_str(), nullptr);
-
-		// exec will only return if it errored, so we should exit with non-zero.
-		_exit(1);
-	}
-	else if (pid > 0) // Parent process.
-	{
-		// Wait for xdg-open to complete (or fail.)
-		int status = 0;
-		if (waitpid(pid, &status, 0) == pid)
-			success = (status == 0);
-		else
-			success = false;
-	}
+	pid_t pid;
+	const char *argv[] = {"xdg-open", url.c_str(), nullptr};
+
+	// Note: at the moment this process inherits our file descriptors.
+	// Note: the below const_cast is really ugly as well.
+	if (posix_spawnp(&pid, "xdg-open", nullptr, nullptr, const_cast<char **>(argv), environ) != 0)
+		return false;
+
+	// Wait for xdg-open to complete (or fail.)
+	int status = 0;
+	if (waitpid(pid, &status, 0) == pid)
+		return (status == 0);
 	else
-	{
-		// vfork() failed.
-		success = false;
-	}
+		return false;
 
 #elif defined(LOVE_WINDOWS)
 
@@ -109,11 +105,9 @@ bool System::openURL(const std::string &url) const
 	                                 nullptr,
 	                                 SW_SHOW);
 
-	success = (int) result > 32;
+	return (int) result > 32;
 
 #endif
-
-	return success;
 }
 
 bool System::getConstant(const char *in, System::PowerState &out)