mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
r=dbragg, sr=mscott, a=asa For the nsIProcess component, which is only used by XPInstall, instead of calling nspr for process creation, we call a simplified version which, on windows, will cause the child process not to inherit fds open by the forking process. Fix is only XP_WIN. nspr will provide a more risky, non-nsIProcess, XP solution at some point which is either achieved by modifying open() to accept a non-inherit flag (on win32) or do an fcntl() on Unix (see the bug for details specific to the fcntl()), or provide another pair of create processes functions that are geared towards non-inheriting process creation. The bug fixed here is the XP installer is not able, on win32, to remove the components.reg file from the "cleanup" process, which leads to all sorts of mayhem, because the cleanup process inherits the component.reg fd which is open at the time the cleanup process is forked, and this it cannot remove something it has an open reference to.
This commit is contained in:
parent
2874ad6931
commit
b3a0275496
@ -38,6 +38,13 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined( XP_WIN )
|
||||
#include "nsString.h"
|
||||
#include "nsLiteralString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------//
|
||||
// nsIProcess implementation
|
||||
//-------------------------------------------------------------------//
|
||||
@ -102,14 +109,74 @@ nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid
|
||||
// null terminate the array
|
||||
my_argv[count+1] = NULL;
|
||||
|
||||
if (blocking)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
STARTUPINFO startupInfo;
|
||||
PROCESS_INFORMATION procInfo;
|
||||
BOOL retVal;
|
||||
|
||||
ZeroMemory(&startupInfo, sizeof(startupInfo));
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
|
||||
retVal = CreateProcess(NULL,
|
||||
NS_CONST_CAST(char*, mTargetPath.get()),
|
||||
NULL, /* security attributes for the new
|
||||
* process */
|
||||
NULL, /* security attributes for the primary
|
||||
* thread in the new process */
|
||||
FALSE, /* inherit handles */
|
||||
0, /* creation flags */
|
||||
NULL, /* env */
|
||||
NULL, /* current drive and directory */
|
||||
&startupInfo,
|
||||
&procInfo
|
||||
);
|
||||
|
||||
if (blocking) {
|
||||
|
||||
// if success, wait for process termination. the early returns and such
|
||||
// are a bit ugly but preserving the logic of the nspr code I copied to
|
||||
// minimize our risk abit.
|
||||
|
||||
if ( retVal == TRUE ) {
|
||||
DWORD dwRetVal;
|
||||
unsigned long exitCode;
|
||||
|
||||
dwRetVal = WaitForSingleObject(procInfo.hProcess, INFINITE);
|
||||
if (dwRetVal == WAIT_FAILED) {
|
||||
nsMemory::Free(my_argv);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
if (GetExitCodeProcess(procInfo.hProcess, &exitCode) == FALSE) {
|
||||
mExitValue = exitCode;
|
||||
nsMemory::Free(my_argv);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
mExitValue = exitCode;
|
||||
CloseHandle(procInfo.hProcess);
|
||||
}
|
||||
else
|
||||
rv = PR_FAILURE;
|
||||
}
|
||||
else {
|
||||
|
||||
// map return value into success code
|
||||
|
||||
if ( retVal == TRUE )
|
||||
rv = PR_SUCCESS;
|
||||
else
|
||||
rv = PR_FAILURE;
|
||||
}
|
||||
|
||||
#else
|
||||
if ( blocking ) {
|
||||
mProcess = PR_CreateProcess(mTargetPath, my_argv, NULL, NULL);
|
||||
if (mProcess)
|
||||
rv = PR_WaitProcess(mProcess, &mExitValue);
|
||||
}
|
||||
else
|
||||
else {
|
||||
rv = PR_CreateProcessDetached(mTargetPath, my_argv, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
// free up our argv
|
||||
nsMemory::Free(my_argv);
|
||||
|
Loading…
Reference in New Issue
Block a user