Merge. a=blockers

This commit is contained in:
Robert Sayre 2010-10-01 09:05:04 -04:00
commit a5e3bc4859
2 changed files with 110 additions and 63 deletions

View File

@ -52,8 +52,10 @@
#include "nsIWeakReferenceUtils.h" #include "nsIWeakReferenceUtils.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsString.h" #include "nsString.h"
#ifndef XP_MACOSX
#include "prproces.h" #include "prproces.h"
#if defined(PROCESSMODEL_WINAPI) #endif
#if defined(PROCESSMODEL_WINAPI)
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>
#endif #endif
@ -77,14 +79,15 @@ private:
~nsProcess(); ~nsProcess();
static void PR_CALLBACK Monitor(void *arg); static void PR_CALLBACK Monitor(void *arg);
void ProcessComplete(); void ProcessComplete();
NS_IMETHOD CopyArgsAndRunProcess(PRBool blocking, const char** args, nsresult CopyArgsAndRunProcess(PRBool blocking, const char** args,
PRUint32 count, nsIObserver* observer, PRUint32 count, nsIObserver* observer,
PRBool holdWeak); PRBool holdWeak);
NS_IMETHOD CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args, nsresult CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args,
PRUint32 count, nsIObserver* observer, PRUint32 count, nsIObserver* observer,
PRBool holdWeak); PRBool holdWeak);
NS_IMETHOD RunProcess(PRBool blocking, char **args, PRUint32 count, // The 'args' array is null-terminated.
nsIObserver* observer, PRBool holdWeak, PRBool argsUTF8); nsresult RunProcess(PRBool blocking, char **args, nsIObserver* observer,
PRBool holdWeak, PRBool argsUTF8);
PRThread* mThread; PRThread* mThread;
PRLock* mLock; PRLock* mLock;
@ -99,10 +102,10 @@ private:
// These members are modified by multiple threads, any accesses should be // These members are modified by multiple threads, any accesses should be
// protected with mLock. // protected with mLock.
PRInt32 mExitValue; PRInt32 mExitValue;
#if defined(PROCESSMODEL_WINAPI) #if defined(PROCESSMODEL_WINAPI)
typedef DWORD (WINAPI*GetProcessIdPtr)(HANDLE process); typedef DWORD (WINAPI*GetProcessIdPtr)(HANDLE process);
HANDLE mProcess; HANDLE mProcess;
#else #elif !defined(XP_MACOSX)
PRProcess *mProcess; PRProcess *mProcess;
#endif #endif
}; };

View File

@ -66,6 +66,10 @@
#include "nsLiteralString.h" #include "nsLiteralString.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#else #else
#ifdef XP_MACOSX
#include <spawn.h>
#include <sys/wait.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#endif #endif
@ -79,6 +83,18 @@
#define ShellExecuteExW ShellExecuteEx #define ShellExecuteExW ShellExecuteEx
#endif #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 // nsIProcess implementation
//-------------------------------------------------------------------// //-------------------------------------------------------------------//
@ -87,14 +103,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsProcess, nsIProcess,
//Constructor //Constructor
nsProcess::nsProcess() nsProcess::nsProcess()
: mThread(nsnull), : mThread(nsnull)
mLock(PR_NewLock()), , mLock(PR_NewLock())
mShutdown(PR_FALSE), , mShutdown(PR_FALSE)
mPid(-1), , mPid(-1)
mObserver(nsnull), , mObserver(nsnull)
mWeakObserver(nsnull), , mWeakObserver(nsnull)
mExitValue(-1), , mExitValue(-1)
mProcess(nsnull) #if !defined(XP_MACOSX)
, mProcess(nsnull)
#endif
{ {
} }
@ -264,15 +282,24 @@ void PR_CALLBACK nsProcess::Monitor(void *arg)
if (process->mShutdown) if (process->mShutdown)
return; 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 #else
PRInt32 exitCode = -1; PRInt32 exitCode = -1;
if (PR_WaitProcess(process->mProcess, &exitCode) != PR_SUCCESS) if (PR_WaitProcess(process->mProcess, &exitCode) != PR_SUCCESS)
exitCode = -1; exitCode = -1;
#endif
// Lock in case Kill or GetExitCode are called during this // Lock in case Kill or GetExitCode are called during this
{ {
nsAutoLock lock(process->mLock); nsAutoLock lock(process->mLock);
#if !defined(XP_MACOSX)
process->mProcess = nsnull; process->mProcess = nsnull;
#endif
process->mExitValue = exitCode; process->mExitValue = exitCode;
if (process->mShutdown) if (process->mShutdown)
return; return;
@ -336,33 +363,27 @@ nsProcess::RunAsync(const char **args, PRUint32 count,
return CopyArgsAndRunProcess(PR_FALSE, args, count, observer, holdWeak); return CopyArgsAndRunProcess(PR_FALSE, args, count, observer, holdWeak);
} }
NS_IMETHODIMP nsresult
nsProcess::CopyArgsAndRunProcess(PRBool blocking, const char** args, nsProcess::CopyArgsAndRunProcess(PRBool blocking, const char** args,
PRUint32 count, nsIObserver* observer, PRUint32 count, nsIObserver* observer,
PRBool holdWeak) PRBool holdWeak)
{ {
// make sure that when we allocate we have 1 greater than the // Add one to the count for the program name and one for NULL termination.
// count since we need to null terminate the list for the argv to
// pass into PR_CreateProcess
char **my_argv = NULL; 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) { if (!my_argv) {
return NS_ERROR_OUT_OF_MEMORY; 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); my_argv[0] = ToNewUTF8String(mTargetPath);
// null terminate the array
my_argv[count+1] = NULL;
nsresult rv = for (PRUint32 i = 0; i < count; i++) {
RunProcess(blocking, my_argv, count, observer, holdWeak, PR_FALSE); 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[0]);
NS_Free(my_argv); NS_Free(my_argv);
@ -384,43 +405,38 @@ nsProcess::RunwAsync(const PRUnichar **args, PRUint32 count,
return CopyArgsAndRunProcessw(PR_FALSE, args, count, observer, holdWeak); return CopyArgsAndRunProcessw(PR_FALSE, args, count, observer, holdWeak);
} }
NS_IMETHODIMP nsresult
nsProcess::CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args, nsProcess::CopyArgsAndRunProcessw(PRBool blocking, const PRUnichar** args,
PRUint32 count, nsIObserver* observer, PRUint32 count, nsIObserver* observer,
PRBool holdWeak) PRBool holdWeak)
{ {
// make sure that when we allocate we have 1 greater than the // Add one to the count for the program name and one for NULL termination.
// count since we need to null terminate the list for the argv to
// pass into PR_CreateProcess
char **my_argv = NULL; 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) { if (!my_argv) {
return NS_ERROR_OUT_OF_MEMORY; 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); my_argv[0] = ToNewUTF8String(mTargetPath);
// null terminate the array
my_argv[count+1] = NULL;
nsresult rv = for (PRUint32 i = 0; i < count; i++) {
RunProcess(blocking, my_argv, count, observer, holdWeak, PR_TRUE); 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[i]);
} }
NS_Free(my_argv); NS_Free(my_argv);
return rv; return rv;
} }
NS_IMETHODIMP nsresult
nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count, nsProcess::RunProcess(PRBool blocking, char **my_argv, nsIObserver* observer,
nsIObserver* observer, PRBool holdWeak, PRBool argsUTF8) PRBool holdWeak, PRBool argsUTF8)
{ {
NS_ENSURE_TRUE(mExecutable, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mExecutable, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_FALSE(mThread, NS_ERROR_ALREADY_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) #if defined(PROCESSMODEL_WINAPI)
BOOL retVal; BOOL retVal;
PRUnichar *cmdLine; PRUnichar *cmdLine = NULL;
if (count > 0 && assembleCmdLine(my_argv + 1, &cmdLine, // The 'argv' array is null-terminated and always starts with the program path.
argsUTF8 ? CP_UTF8 : CP_ACP) == -1) { // 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; 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_NO_CONSOLE |
SEE_MASK_NOCLOSEPROCESS; SEE_MASK_NOCLOSEPROCESS;
if (count > 0) if (cmdLine)
sinfo.lpParameters = cmdLine; sinfo.lpParameters = cmdLine;
retVal = ShellExecuteExW(&sinfo); retVal = ShellExecuteExW(&sinfo);
@ -479,8 +497,8 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count,
mProcess = sinfo.hProcess; mProcess = sinfo.hProcess;
PR_Free(wideFile); PR_Free(wideFile);
if (count > 0) if (cmdLine)
PR_Free( cmdLine ); PR_Free(cmdLine);
HMODULE kernelDLL = ::LoadLibraryW(L"kernel32.dll"); HMODULE kernelDLL = ::LoadLibraryW(L"kernel32.dll");
if (kernelDLL) { if (kernelDLL) {
@ -489,13 +507,36 @@ nsProcess::RunProcess(PRBool blocking, char **my_argv, PRUint32 count,
mPid = getProcessId(mProcess); mPid = getProcessId(mProcess);
FreeLibrary(kernelDLL); 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); mProcess = PR_CreateProcess(my_argv[0], my_argv, NULL, NULL);
if (!mProcess) if (!mProcess)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
#if !defined WINCE #if !defined WINCE
struct MYProcess { struct MYProcess {
PRUint32 pid; PRUint32 pid;
@ -562,6 +603,9 @@ nsProcess::Kill()
#if defined(PROCESSMODEL_WINAPI) #if defined(PROCESSMODEL_WINAPI)
if (TerminateProcess(mProcess, NULL) == 0) if (TerminateProcess(mProcess, NULL) == 0)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
#elif defined(XP_MACOSX)
if (kill(mPid, SIGKILL) != 0)
return NS_ERROR_FAILURE;
#else #else
if (!mProcess || (PR_KillProcess(mProcess) != PR_SUCCESS)) if (!mProcess || (PR_KillProcess(mProcess) != PR_SUCCESS))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;