зеркало из https://github.com/mozilla/pjs.git
Bug 600711: Use 'posix_spawnp' for nsIProcess on Mac OS X. Prefer the current architecture when creating a new process. r=bsmedberg a=blocking-beta7
This commit is contained in:
Родитель
9861ce8c55
Коммит
709f37b50e
|
@ -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 <windows.h>
|
||||
#include <shellapi.h>
|
||||
#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
|
||||
};
|
||||
|
|
|
@ -66,6 +66,10 @@
|
|||
#include "nsLiteralString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#else
|
||||
#ifdef XP_MACOSX
|
||||
#include <spawn.h>
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#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<char*>(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<char*>(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<PRInt32>(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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче