diff --git a/xpcom/threads/nsProcess.h b/xpcom/threads/nsProcess.h index 87cbaa6c85ef..303a0281706a 100644 --- a/xpcom/threads/nsProcess.h +++ b/xpcom/threads/nsProcess.h @@ -52,8 +52,10 @@ #include "nsIWeakReferenceUtils.h" #include "nsIObserver.h" #include "nsString.h" +#ifndef XP_MACOSX #include "prproces.h" -#if defined(PROCESSMODEL_WINAPI) +#endif +#if defined(PROCESSMODEL_WINAPI) #include #include #endif @@ -77,14 +79,15 @@ private: ~nsProcess(); static void PR_CALLBACK Monitor(void *arg); void ProcessComplete(); - NS_IMETHOD CopyArgsAndRunProcess(PRBool blocking, const char** args, - PRUint32 count, nsIObserver* observer, - PRBool holdWeak); - NS_IMETHOD CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args, - PRUint32 count, nsIObserver* observer, - PRBool holdWeak); - NS_IMETHOD RunProcess(PRBool blocking, char **args, PRUint32 count, - nsIObserver* observer, PRBool holdWeak, PRBool argsUTF8); + nsresult CopyArgsAndRunProcess(PRBool blocking, const char** args, + PRUint32 count, nsIObserver* observer, + PRBool holdWeak); + nsresult CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args, + PRUint32 count, nsIObserver* observer, + PRBool holdWeak); + // The 'args' array is null-terminated. + nsresult RunProcess(PRBool blocking, char **args, nsIObserver* observer, + PRBool holdWeak, PRBool argsUTF8); PRThread* mThread; PRLock* mLock; @@ -99,10 +102,10 @@ private: // These members are modified by multiple threads, any accesses should be // protected with mLock. PRInt32 mExitValue; -#if defined(PROCESSMODEL_WINAPI) +#if defined(PROCESSMODEL_WINAPI) typedef DWORD (WINAPI*GetProcessIdPtr)(HANDLE process); HANDLE mProcess; -#else +#elif !defined(XP_MACOSX) PRProcess *mProcess; #endif }; diff --git a/xpcom/threads/nsProcessCommon.cpp b/xpcom/threads/nsProcessCommon.cpp index dcb3ce479df2..ec9b4c1eb913 100644 --- a/xpcom/threads/nsProcessCommon.cpp +++ b/xpcom/threads/nsProcessCommon.cpp @@ -66,6 +66,10 @@ #include "nsLiteralString.h" #include "nsReadableUtils.h" #else +#ifdef XP_MACOSX +#include +#include +#endif #include #include #endif @@ -79,6 +83,18 @@ #define ShellExecuteExW ShellExecuteEx #endif +#ifdef XP_MACOSX +cpu_type_t pref_cpu_types[2] = { +#if defined(__i386__) + CPU_TYPE_X86, +#elif defined(__x86_64__) + CPU_TYPE_X86_64, +#elif defined(__ppc__) + CPU_TYPE_POWERPC, +#endif + CPU_TYPE_ANY }; +#endif + //-------------------------------------------------------------------// // nsIProcess implementation //-------------------------------------------------------------------// @@ -87,14 +103,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsProcess, nsIProcess, //Constructor nsProcess::nsProcess() - : mThread(nsnull), - mLock(PR_NewLock()), - mShutdown(PR_FALSE), - mPid(-1), - mObserver(nsnull), - mWeakObserver(nsnull), - mExitValue(-1), - mProcess(nsnull) + : mThread(nsnull) + , mLock(PR_NewLock()) + , mShutdown(PR_FALSE) + , mPid(-1) + , mObserver(nsnull) + , mWeakObserver(nsnull) + , mExitValue(-1) +#if !defined(XP_MACOSX) + , mProcess(nsnull) +#endif { } @@ -264,15 +282,24 @@ void PR_CALLBACK nsProcess::Monitor(void *arg) if (process->mShutdown) return; } +#else +#ifdef XP_MACOSX + int exitCode = -1; + int status = 0; + if (waitpid(process->mPid, &status, 0) == process->mPid && WIFEXITED(status)) + exitCode = WEXITSTATUS(status); #else PRInt32 exitCode = -1; if (PR_WaitProcess(process->mProcess, &exitCode) != PR_SUCCESS) exitCode = -1; +#endif // Lock in case Kill or GetExitCode are called during this { nsAutoLock lock(process->mLock); +#if !defined(XP_MACOSX) process->mProcess = nsnull; +#endif process->mExitValue = exitCode; if (process->mShutdown) return; @@ -336,33 +363,27 @@ nsProcess::RunAsync(const char **args, PRUint32 count, return CopyArgsAndRunProcess(PR_FALSE, args, count, observer, holdWeak); } -NS_IMETHODIMP +nsresult nsProcess::CopyArgsAndRunProcess(PRBool blocking, const char** args, PRUint32 count, nsIObserver* observer, PRBool holdWeak) { - // make sure that when we allocate we have 1 greater than the - // count since we need to null terminate the list for the argv to - // pass into PR_CreateProcess + // Add one to the count for the program name and one for NULL termination. char **my_argv = NULL; - my_argv = (char **)NS_Alloc(sizeof(char *) * (count + 2) ); + my_argv = (char**)NS_Alloc(sizeof(char*) * (count + 2)); if (!my_argv) { return NS_ERROR_OUT_OF_MEMORY; } - // copy the args - PRUint32 i; - for (i=0; i < count; i++) { - my_argv[i+1] = const_cast(args[i]); - printf("arg[%d] = %s\n", i, my_argv[i+1]); - } - // we need to set argv[0] to the program name. my_argv[0] = ToNewUTF8String(mTargetPath); - // null terminate the array - my_argv[count+1] = NULL; - nsresult rv = - RunProcess(blocking, my_argv, count, observer, holdWeak, PR_FALSE); + for (PRUint32 i = 0; i < count; i++) { + my_argv[i + 1] = const_cast(args[i]); + } + + my_argv[count + 1] = NULL; + + nsresult rv = RunProcess(blocking, my_argv, observer, holdWeak, PR_FALSE); NS_Free(my_argv[0]); NS_Free(my_argv); @@ -384,43 +405,38 @@ nsProcess::RunwAsync(const PRUnichar **args, PRUint32 count, return CopyArgsAndRunProcessw(PR_FALSE, args, count, observer, holdWeak); } -NS_IMETHODIMP +nsresult nsProcess::CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args, PRUint32 count, nsIObserver* observer, PRBool holdWeak) { - // make sure that when we allocate we have 1 greater than the - // count since we need to null terminate the list for the argv to - // pass into PR_CreateProcess + // Add one to the count for the program name and one for NULL termination. char **my_argv = NULL; - my_argv = (char **)NS_Alloc(sizeof(char *) * (count + 2) ); + my_argv = (char**)NS_Alloc(sizeof(char*) * (count + 2)); if (!my_argv) { return NS_ERROR_OUT_OF_MEMORY; } - // copy the args - PRUint32 i; - for (i=0; i < count; i++) { - my_argv[i+1] = ToNewUTF8String(nsDependentString(args[i])); - } - // we need to set argv[0] to the program name. my_argv[0] = ToNewUTF8String(mTargetPath); - // null terminate the array - my_argv[count+1] = NULL; - nsresult rv = - RunProcess(blocking, my_argv, count, observer, holdWeak, PR_TRUE); + for (PRUint32 i = 0; i < count; i++) { + my_argv[i + 1] = ToNewUTF8String(nsDependentString(args[i])); + } - for (i=0; i <= count; ++i) { + my_argv[count + 1] = NULL; + + nsresult rv = RunProcess(blocking, my_argv, observer, holdWeak, PR_TRUE); + + for (PRUint32 i = 0; i <= count; i++) { NS_Free(my_argv[i]); } NS_Free(my_argv); return rv; } -NS_IMETHODIMP -nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, - nsIObserver* observer, PRBool holdWeak, PRBool argsUTF8) +nsresult +nsProcess::RunProcess(PRBool blocking, char **my_argv, nsIObserver* observer, + PRBool holdWeak, PRBool argsUTF8) { NS_ENSURE_TRUE(mExecutable, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_FALSE(mThread, NS_ERROR_ALREADY_INITIALIZED); @@ -441,10 +457,12 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, #if defined(PROCESSMODEL_WINAPI) BOOL retVal; - PRUnichar *cmdLine; + PRUnichar *cmdLine = NULL; - if (count > 0 && assembleCmdLine(my_argv + 1, &cmdLine, - argsUTF8 ? CP_UTF8 : CP_ACP) == -1) { + // The 'argv' array is null-terminated and always starts with the program path. + // If the second slot is non-null then arguments are being passed. + if (my_argv[1] != NULL && + assembleCmdLine(my_argv + 1, &cmdLine, argsUTF8 ? CP_UTF8 : CP_ACP) == -1) { return NS_ERROR_FILE_EXECUTION_FAILED; } @@ -468,7 +486,7 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; - if (count > 0) + if (cmdLine) sinfo.lpParameters = cmdLine; retVal = ShellExecuteExW(&sinfo); @@ -479,8 +497,8 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, mProcess = sinfo.hProcess; PR_Free(wideFile); - if (count > 0) - PR_Free( cmdLine ); + if (cmdLine) + PR_Free(cmdLine); HMODULE kernelDLL = ::LoadLibraryW(L"kernel32.dll"); if (kernelDLL) { @@ -489,13 +507,36 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, mPid = getProcessId(mProcess); FreeLibrary(kernelDLL); } +#elif defined(XP_MACOSX) + // Initialize spawn attributes. + posix_spawnattr_t spawnattr; + if (posix_spawnattr_init(&spawnattr) != 0) { + return NS_ERROR_FAILURE; + } -#else // Note, this must not be an #elif ...! - + // Set spawn attributes. + size_t attr_count = NS_ARRAY_LENGTH(pref_cpu_types); + size_t attr_ocount = 0; + if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, pref_cpu_types, &attr_ocount) != 0 || + attr_ocount != attr_count) { + posix_spawnattr_destroy(&spawnattr); + return NS_ERROR_FAILURE; + } + + // Note that the 'argv' array is already null-terminated, which 'posix_spawnp' requires. + pid_t newPid = 0; + int result = posix_spawnp(&newPid, my_argv[0], NULL, &spawnattr, my_argv, NULL); + mPid = static_cast(newPid); + + posix_spawnattr_destroy(&spawnattr); + + if (result != 0) { + return NS_ERROR_FAILURE; + } +#else mProcess = PR_CreateProcess(my_argv[0], my_argv, NULL, NULL); if (!mProcess) return NS_ERROR_FAILURE; - #if !defined WINCE struct MYProcess { PRUint32 pid; @@ -562,6 +603,9 @@ nsProcess::Kill() #if defined(PROCESSMODEL_WINAPI) if (TerminateProcess(mProcess, NULL) == 0) return NS_ERROR_FAILURE; +#elif defined(XP_MACOSX) + if (kill(mPid, SIGKILL) != 0) + return NS_ERROR_FAILURE; #else if (!mProcess || (PR_KillProcess(mProcess) != PR_SUCCESS)) return NS_ERROR_FAILURE;