--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -67,19 +67,16 @@ CPPSRCS = \
TestCallTemplates.cpp \
TestINIParser.cpp \
TestVersionComparator.cpp \
TestRacingServiceManager.cpp \
TestRegistrationOrder.cpp \
TestThreadPoolListener.cpp \
TestTimers.cpp \
TestOOM.cpp \
- TestBlockingProcess.cpp \
- TestQuickReturn.cpp \
- TestArguments.cpp \
$(NULL)
ifndef MOZ_ENABLE_LIBXUL
CPPSRCS += \
TestAtoms.cpp \
TestPermanentAtoms.cpp \
$(NULL)
endif
deleted file mode 100644
--- a/xpcom/tests/TestArguments.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <iostream>
-#include <string>
-
-using namespace std;
-
-int main(int argc, char* argv[]) {
-
- string test = "mozilla";
-
- if (test.compare(argv[1]) != 0)
- return -1;
-
- return 0;
-}
deleted file mode 100644
--- a/xpcom/tests/TestBlockingProcess.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-
-int main()
-{
- char text[20];
- fgets(text, sizeof text, stdin);
- return 0;
-}
-
deleted file mode 100644
--- a/xpcom/tests/TestQuickReturn.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main () {
-
- return 42;
-}
deleted file mode 100644
--- a/xpcom/tests/unit/test_nsIProcess.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is XPCOM unit tests.
- *
- * The Initial Developer of the Original Code is
- * James Boston <mozilla@jamesboston.ca>.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-// nsIProcess unit test
-
-// get the path to {objdir}/dist/bin
-var bindir = Components.classes["@mozilla.org/file/directory_service;1"]
-.getService(Components.interfaces.nsIProperties)
-.get("CurProcD", Components.interfaces.nsIFile);
-
-// the the os
-var isWindows = ("@mozilla.org/windows-registry-key;1" in Components.classes);
-
-var filePrefix = "";
-var fileSuffix = "";
-
-if (isWindows) {
- filePrefix = bindir.path + "\\";
- fileSuffix = ".exe";
-} else {
- filePrefix = bindir.path + "/";
-}
-
-
-// test if a process can be started, polled for its running status
-// and then killed
-function test_kill()
-{
- var testapp = filePrefix + "TestBlockingProcess" +fileSuffix;
- print(testapp);
-
- var file = Components.classes["@mozilla.org/file/local;1"]
- .createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(testapp);
-
- var process = Components.classes["@mozilla.org/process/util;1"]
- .createInstance(Components.interfaces.nsIProcess);
- process.init(file);
-
- var pid = process.run(false, [], 0);
-
- if (!pid) {
- return false;
- }
-
- var rv = process.isRunning;
-
- if (!rv) {
- return false;
- }
-
- process.kill();
-
- rv = process.isRunning;
-
- if (rv){
- return false;
- }
- return true;
-
-}
-
-// test if we can get an exit value from an application that is
-// guaranteed to return an exit value of 42
-function test_quick()
-{
- var testapp = filePrefix + "TestQuickReturn" + fileSuffix;
-
- var file = Components.classes["@mozilla.org/file/local;1"]
- .createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(testapp);
-
- var process = Components.classes["@mozilla.org/process/util;1"]
- .createInstance(Components.interfaces.nsIProcess);
- process.init(file);
-
- // to get an exit value it must be a blocking process
- var pid = process.run(true, [], 0);
-
- if (!pid) {
- return false;
- }
-
- if (process.exitValue != 42) {
- return false;
- }
- return true;
-}
-
-// test if an argument can be successfully passed to an application
-// that will return -1 if "mozilla" is not the first argument
-function test_arguments()
-{
- var testapp = filePrefix + "TestArguments" + fileSuffix;
-
- var file = Components.classes["@mozilla.org/file/local;1"]
- .createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(testapp);
-
- var process = Components.classes["@mozilla.org/process/util;1"]
- .createInstance(Components.interfaces.nsIProcess);
- process.init(file);
-
- var args= ["mozilla"];
-
- var pid = process.run(true, args, args.length);
-
- if (!pid) {
- return false;
- }
-
- if (process.exitValue) {
- return false;
- }
- return true;
-}
-
-function run_test() {
- do_check_true(test_kill());
- do_check_true(test_quick());
- do_check_true(test_arguments());
-}
--- a/xpcom/threads/nsIProcess.idl
+++ b/xpcom/threads/nsIProcess.idl
@@ -1,12 +1,12 @@
#include "nsIFile.idl"
#include "nsISupports.idl"
-[scriptable, uuid(d573f1f3-fcdd-4dbe-980b-4ba79e6718dc)]
+[scriptable, uuid(9da0b650-d07e-4617-a18a-250035572ac8)]
interface nsIProcess : nsISupports
{
void init(in nsIFile executable);
void initWithPid(in unsigned long pid);
void kill();
@@ -18,16 +18,15 @@ interface nsIProcess : nsISupports
* @return the PID of the newly spawned process */
unsigned long run(in boolean blocking, [array, size_is(count)] in string args, in unsigned long count);
readonly attribute nsIFile location;
readonly attribute unsigned long pid;
readonly attribute string processName;
readonly attribute unsigned long processSignature;
readonly attribute long exitValue;
- readonly attribute unsigned long isRunning;
};
%{C++
#define NS_PROCESS_CONTRACTID "@mozilla.org/process/util;1"
#define NS_PROCESS_CLASSNAME "Process Specification"
%}
--- a/xpcom/threads/nsProcess.h
+++ b/xpcom/threads/nsProcess.h
@@ -35,47 +35,37 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsPROCESSWIN_H_
#define _nsPROCESSWIN_H_
-#if defined(XP_WIN) && !defined (WINCE) /* wince uses nspr */
-#define PROCESSMODEL_WINAPI
-#endif
-
#include "nsIProcess.h"
#include "nsIFile.h"
#include "nsString.h"
#include "prproces.h"
-#if defined(PROCESSMODEL_WINAPI)
-#include <windows.h>
-#endif
#define NS_PROCESS_CID \
{0x7b4eeb20, 0xd781, 0x11d4, \
{0x8A, 0x83, 0x00, 0x10, 0xa4, 0xe0, 0xc9, 0xca}}
class nsProcess : public nsIProcess
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROCESS
nsProcess();
private:
- ~nsProcess();
+ ~nsProcess() {}
nsCOMPtr<nsIFile> mExecutable;
PRInt32 mExitValue;
nsCString mTargetPath;
PRProcess *mProcess;
-#if defined(PROCESSMODEL_WINAPI)
- PROCESS_INFORMATION procInfo;
-#endif
};
#endif
--- a/xpcom/threads/nsProcessCommon.cpp
+++ b/xpcom/threads/nsProcessCommon.cpp
@@ -56,62 +56,38 @@
#include <stdlib.h>
#if defined(XP_WIN)
#include "prmem.h"
#include "nsString.h"
#include "nsLiteralString.h"
#include "nsReadableUtils.h"
#include <windows.h>
-#else
-#include <sys/types.h>
-#include <signal.h>
+#endif
+
+#if defined(XP_MACOSX)
+#include <Processes.h>
+#include "nsILocalFileMac.h"
#endif
//-------------------------------------------------------------------//
// nsIProcess implementation
//-------------------------------------------------------------------//
NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
//Constructor
nsProcess::nsProcess()
: mExitValue(-1),
mProcess(nsnull)
{
-#if defined(PROCESSMODEL_WINAPI)
- procInfo.dwProcessId = nsnull;
-#endif
-}
-
-//Destructor
-nsProcess::~nsProcess()
-{
-#if defined(PROCESSMODEL_WINAPI)
- if (procInfo.dwProcessId) {
- CloseHandle( procInfo.hProcess );
- CloseHandle( procInfo.hThread );
- }
-#else
- if (mProcess)
- PR_DetachProcess(mProcess);
-#endif
}
NS_IMETHODIMP
nsProcess::Init(nsIFile* executable)
{
- //Prevent re-initializing if already attached to process
-#if defined(PROCESSMODEL_WINAPI)
- if (procInfo.dwProcessId)
- return NS_ERROR_ALREADY_INITIALIZED;
-#else
- if (mProcess)
- return NS_ERROR_ALREADY_INITIALIZED;
-#endif
-
NS_ENSURE_ARG_POINTER(executable);
PRBool isFile;
//First make sure the file exists
nsresult rv = executable->IsFile(&isFile);
if (NS_FAILED(rv)) return rv;
if (!isFile)
return NS_ERROR_FAILURE;
@@ -260,18 +236,19 @@ nsProcess::Run(PRBool blocking, const ch
for (i=0; i < count; i++) {
my_argv[i+1] = const_cast<char*>(args[i]);
}
// we need to set argv[0] to the program name.
my_argv[0] = mTargetPath.BeginWriting();
// null terminate the array
my_argv[count+1] = NULL;
-#if defined(PROCESSMODEL_WINAPI)
+#if defined(XP_WIN) && !defined (WINCE) /* wince uses nspr */
STARTUPINFOW startupInfo;
+ PROCESS_INFORMATION procInfo;
BOOL retVal;
PRUnichar *cmdLine;
if (assembleCmdLine(my_argv, &cmdLine) == -1) {
nsMemory::Free(my_argv);
return NS_ERROR_FILE_EXECUTION_FAILED;
}
@@ -293,17 +270,16 @@ nsProcess::Run(PRBool blocking, const ch
* thread in the new process */
FALSE, /* inherit handles */
CREATE_NO_WINDOW, /* creation flags */
NULL, /* env */
NULL, /* current drive and directory */
&startupInfo,
&procInfo
);
- *pid = procInfo.dwProcessId;
PR_Free( cmdLine );
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 ) {
@@ -318,108 +294,125 @@ nsProcess::Run(PRBool blocking, const ch
if (GetExitCodeProcess(procInfo.hProcess, &exitCode) == FALSE) {
mExitValue = exitCode;
nsMemory::Free(my_argv);
return NS_ERROR_FAILURE;
}
mExitValue = exitCode;
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
- procInfo.dwProcessId = nsnull;
}
else
status = PR_FAILURE;
}
else {
// map return value into success code
if (retVal == TRUE)
status = PR_SUCCESS;
else
status = PR_FAILURE;
}
#else // Note, this must not be an #elif ...!
-
- mProcess = PR_CreateProcess(mTargetPath.get(), my_argv, NULL, NULL);
- if (mProcess) {
- GetPid(pid);
- status = PR_SUCCESS;
+
+#if defined(XP_MACOSX)
+ if (count == 0) {
+ FSSpec resolvedSpec;
+ OSErr err = noErr;
+
+ nsCOMPtr<nsILocalFileMac> macExecutable =
+ do_QueryInterface(mExecutable);
+ macExecutable->GetFSSpec(&resolvedSpec);
+
+ LaunchParamBlockRec launchPB;
+ launchPB.launchAppSpec = &resolvedSpec;
+ launchPB.launchAppParameters = NULL;
+ launchPB.launchBlockID = extendedBlock;
+ launchPB.launchEPBLength = extendedBlockLen;
+ launchPB.launchFileFlags = NULL;
+ launchPB.launchControlFlags =
+ launchContinue + launchNoFileFlags + launchUseMinimum;
+ if (!blocking)
+ launchPB.launchControlFlags += launchDontSwitch;
+
+ err = LaunchApplication(&launchPB);
+
+ // NOTE: blocking mode assumes you are running on a thread
+ // other than the UI thread that has the main event loop
+ if (blocking && err == noErr) {
+ while (1) {
+ ProcessInfoRec info;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = NULL;
+ info.processAppSpec = NULL;
+
+ err = GetProcessInformation(&launchPB.launchProcessSN, &info);
+
+ if (err != noErr) {
+ // The process is no longer in the process
+ // manager's internal list, assume the process is
+ // done.
+ err = noErr;
+
+ break;
+ }
+
+ // still running so sleep some more (200 msecs)
+ PR_Sleep(200);
+ }
+ }
+
+ if (err != noErr) {
+ status = PR_FAILURE;
+ }
+
if (blocking) {
- status = PR_WaitProcess(mProcess, &mExitValue);
- mProcess = nsnull;
- }
+ mExitValue = err;
+ }
+ } else
+#endif
+ {
+ if (blocking) {
+ mProcess = PR_CreateProcess(mTargetPath.get(), my_argv, NULL,
+ NULL);
+ if (mProcess)
+ status = PR_WaitProcess(mProcess, &mExitValue);
+ } else {
+ status = PR_CreateProcessDetached(mTargetPath.get(), my_argv, NULL,
+ NULL);
+ }
}
#endif
// free up our argv
nsMemory::Free(my_argv);
if (status != PR_SUCCESS)
return NS_ERROR_FILE_EXECUTION_FAILED;
return NS_OK;
}
-NS_IMETHODIMP nsProcess::GetIsRunning(PRUint32 *aIsRunning)
-{
-#if defined(PROCESSMODEL_WINAPI)
- DWORD ec = 0;
- BOOL br = GetExitCodeProcess(procInfo.hProcess, &ec);
- if (!br) {
- aIsRunning = 0;
- return NS_OK;
- }
- *aIsRunning = (ec == STILL_ACTIVE ? 1 : 0);
- return NS_OK;
-#elif defined WINCE
- return NS_ERROR_NOT_IMPLEMENTED;
-#else
- PRUint32 pid;
- GetPid(&pid);
- if (pid)
- *aIsRunning = (kill(pid, 0) != -1) ? 1 : 0;
- return NS_OK;
-#endif
-}
-
NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsProcess::GetLocation(nsIFile** aLocation)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsProcess::GetPid(PRUint32 *aPid)
{
-#if defined(PROCESSMODEL_WINAPI)
- if (!procInfo.dwProcessId)
- return NS_ERROR_FAILURE;
- *aPid = procInfo.dwProcessId;
- return NS_OK;
-#elif defined WINCE
return NS_ERROR_NOT_IMPLEMENTED;
-#else
- if (!mProcess) {
- *aPid = 0;
- return NS_ERROR_FAILURE;
- }
- struct MYProcess {
- PRUint32 pid;
- };
- MYProcess* ptrProc = (MYProcess *) mProcess;
- *aPid = ptrProc->pid;
- return NS_OK;
-#endif
}
NS_IMETHODIMP
nsProcess::GetProcessName(char** aProcessName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
@@ -428,30 +421,19 @@ nsProcess::GetProcessSignature(PRUint32
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsProcess::Kill()
{
nsresult rv = NS_OK;
-#if defined(PROCESSMODEL_WINAPI)
- if ( TerminateProcess(procInfo.hProcess, NULL) == 0 ) {
- rv = NS_ERROR_FAILURE;
- }
- else {
- CloseHandle( procInfo.hProcess );
- procInfo.dwProcessId = nsnull;
- }
-#else
if (mProcess)
rv = PR_KillProcess(mProcess) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
- if (rv == NS_OK)
- mProcess = nsnull;
-#endif
+
return rv;
}
NS_IMETHODIMP
nsProcess::GetExitValue(PRInt32 *aExitValue)
{
*aExitValue = mExitValue;