LCOV - code coverage report
Current view: top level - xpcom/threads - nsProcessCommon.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 172 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*****************************************************************************
       8             :  *
       9             :  * nsProcess is used to execute new processes and specify if you want to
      10             :  * wait (blocking) or continue (non-blocking).
      11             :  *
      12             :  *****************************************************************************
      13             :  */
      14             : 
      15             : #include "mozilla/ArrayUtils.h"
      16             : 
      17             : #include "nsCOMPtr.h"
      18             : #include "nsAutoPtr.h"
      19             : #include "nsMemory.h"
      20             : #include "nsProcess.h"
      21             : #include "prio.h"
      22             : #include "prenv.h"
      23             : #include "nsCRT.h"
      24             : #include "nsThreadUtils.h"
      25             : #include "nsIObserverService.h"
      26             : #include "nsXULAppAPI.h"
      27             : #include "mozilla/Services.h"
      28             : #include "GeckoProfiler.h"
      29             : 
      30             : #include <stdlib.h>
      31             : 
      32             : #if defined(PROCESSMODEL_WINAPI)
      33             : #include "nsString.h"
      34             : #include "nsLiteralString.h"
      35             : #include "nsReadableUtils.h"
      36             : #else
      37             : #ifdef XP_MACOSX
      38             : #include <crt_externs.h>
      39             : #include <spawn.h>
      40             : #include <sys/wait.h>
      41             : #include <sys/errno.h>
      42             : #endif
      43             : #include <sys/types.h>
      44             : #include <signal.h>
      45             : #endif
      46             : 
      47             : using namespace mozilla;
      48             : 
      49             : #ifdef XP_MACOSX
      50             : cpu_type_t pref_cpu_types[2] = {
      51             : #if defined(__i386__)
      52             :   CPU_TYPE_X86,
      53             : #elif defined(__x86_64__)
      54             :   CPU_TYPE_X86_64,
      55             : #elif defined(__ppc__)
      56             :   CPU_TYPE_POWERPC,
      57             : #endif
      58             :   CPU_TYPE_ANY
      59             : };
      60             : #endif
      61             : 
      62             : //-------------------------------------------------------------------//
      63             : // nsIProcess implementation
      64             : //-------------------------------------------------------------------//
      65           0 : NS_IMPL_ISUPPORTS(nsProcess, nsIProcess,
      66             :                   nsIObserver)
      67             : 
      68             : //Constructor
      69           0 : nsProcess::nsProcess()
      70             :   : mThread(nullptr)
      71             :   , mLock("nsProcess.mLock")
      72             :   , mShutdown(false)
      73             :   , mBlocking(false)
      74             :   , mStartHidden(false)
      75             :   , mPid(-1)
      76             :   , mObserver(nullptr)
      77             :   , mWeakObserver(nullptr)
      78             :   , mExitValue(-1)
      79             : #if !defined(XP_MACOSX)
      80           0 :   , mProcess(nullptr)
      81             : #endif
      82             : {
      83           0 : }
      84             : 
      85             : //Destructor
      86           0 : nsProcess::~nsProcess()
      87             : {
      88           0 : }
      89             : 
      90             : NS_IMETHODIMP
      91           0 : nsProcess::Init(nsIFile* aExecutable)
      92             : {
      93           0 :   if (mExecutable) {
      94           0 :     return NS_ERROR_ALREADY_INITIALIZED;
      95             :   }
      96             : 
      97           0 :   if (NS_WARN_IF(!aExecutable)) {
      98           0 :     return NS_ERROR_INVALID_ARG;
      99             :   }
     100             :   bool isFile;
     101             : 
     102             :   //First make sure the file exists
     103           0 :   nsresult rv = aExecutable->IsFile(&isFile);
     104           0 :   if (NS_FAILED(rv)) {
     105           0 :     return rv;
     106             :   }
     107           0 :   if (!isFile) {
     108           0 :     return NS_ERROR_FAILURE;
     109             :   }
     110             : 
     111             :   //Store the nsIFile in mExecutable
     112           0 :   mExecutable = aExecutable;
     113             :   //Get the path because it is needed by the NSPR process creation
     114             : #ifdef XP_WIN
     115             :   rv = mExecutable->GetTarget(mTargetPath);
     116             :   if (NS_FAILED(rv) || mTargetPath.IsEmpty())
     117             : #endif
     118           0 :     rv = mExecutable->GetPath(mTargetPath);
     119             : 
     120           0 :   return rv;
     121             : }
     122             : 
     123             : 
     124             : #if defined(XP_WIN)
     125             : // Out param `aWideCmdLine` must be PR_Freed by the caller.
     126             : static int
     127             : assembleCmdLine(char* const* aArgv, wchar_t** aWideCmdLine, UINT aCodePage)
     128             : {
     129             :   char* const* arg;
     130             :   char* p;
     131             :   char* q;
     132             :   char* cmdLine;
     133             :   int cmdLineSize;
     134             :   int numBackslashes;
     135             :   int i;
     136             :   int argNeedQuotes;
     137             : 
     138             :   /*
     139             :    * Find out how large the command line buffer should be.
     140             :    */
     141             :   cmdLineSize = 0;
     142             :   for (arg = aArgv; *arg; ++arg) {
     143             :     /*
     144             :      * \ and " need to be escaped by a \.  In the worst case,
     145             :      * every character is a \ or ", so the string of length
     146             :      * may double.  If we quote an argument, that needs two ".
     147             :      * Finally, we need a space between arguments, and
     148             :      * a null byte at the end of command line.
     149             :      */
     150             :     cmdLineSize += 2 * strlen(*arg)  /* \ and " need to be escaped */
     151             :                    + 2               /* we quote every argument */
     152             :                    + 1;              /* space in between, or final null */
     153             :   }
     154             :   p = cmdLine = (char*) malloc(cmdLineSize * sizeof(char));
     155             :   if (!p) {
     156             :     return -1;
     157             :   }
     158             : 
     159             :   for (arg = aArgv; *arg; ++arg) {
     160             :     /* Add a space to separates the arguments */
     161             :     if (arg != aArgv) {
     162             :       *p++ = ' ';
     163             :     }
     164             :     q = *arg;
     165             :     numBackslashes = 0;
     166             :     argNeedQuotes = 0;
     167             : 
     168             :     /* If the argument contains white space, it needs to be quoted. */
     169             :     if (strpbrk(*arg, " \f\n\r\t\v")) {
     170             :       argNeedQuotes = 1;
     171             :     }
     172             : 
     173             :     if (argNeedQuotes) {
     174             :       *p++ = '"';
     175             :     }
     176             :     while (*q) {
     177             :       if (*q == '\\') {
     178             :         numBackslashes++;
     179             :         q++;
     180             :       } else if (*q == '"') {
     181             :         if (numBackslashes) {
     182             :           /*
     183             :            * Double the backslashes since they are followed
     184             :            * by a quote
     185             :            */
     186             :           for (i = 0; i < 2 * numBackslashes; i++) {
     187             :             *p++ = '\\';
     188             :           }
     189             :           numBackslashes = 0;
     190             :         }
     191             :         /* To escape the quote */
     192             :         *p++ = '\\';
     193             :         *p++ = *q++;
     194             :       } else {
     195             :         if (numBackslashes) {
     196             :           /*
     197             :            * Backslashes are not followed by a quote, so
     198             :            * don't need to double the backslashes.
     199             :            */
     200             :           for (i = 0; i < numBackslashes; i++) {
     201             :             *p++ = '\\';
     202             :           }
     203             :           numBackslashes = 0;
     204             :         }
     205             :         *p++ = *q++;
     206             :       }
     207             :     }
     208             : 
     209             :     /* Now we are at the end of this argument */
     210             :     if (numBackslashes) {
     211             :       /*
     212             :        * Double the backslashes if we have a quote string
     213             :        * delimiter at the end.
     214             :        */
     215             :       if (argNeedQuotes) {
     216             :         numBackslashes *= 2;
     217             :       }
     218             :       for (i = 0; i < numBackslashes; i++) {
     219             :         *p++ = '\\';
     220             :       }
     221             :     }
     222             :     if (argNeedQuotes) {
     223             :       *p++ = '"';
     224             :     }
     225             :   }
     226             : 
     227             :   *p = '\0';
     228             :   int32_t numChars = MultiByteToWideChar(aCodePage, 0, cmdLine, -1, nullptr, 0);
     229             :   *aWideCmdLine = (wchar_t*) malloc(numChars * sizeof(wchar_t));
     230             :   MultiByteToWideChar(aCodePage, 0, cmdLine, -1, *aWideCmdLine, numChars);
     231             :   free(cmdLine);
     232             :   return 0;
     233             : }
     234             : #endif
     235             : 
     236             : void
     237           0 : nsProcess::Monitor(void* aArg)
     238             : {
     239             :   char stackBaseGuess;
     240             : 
     241           0 :   RefPtr<nsProcess> process = dont_AddRef(static_cast<nsProcess*>(aArg));
     242             : 
     243           0 :   if (!process->mBlocking) {
     244           0 :     NS_SetCurrentThreadName("RunProcess");
     245           0 :     profiler_register_thread("RunProcess", &stackBaseGuess);
     246             :   }
     247             : 
     248             : #if defined(PROCESSMODEL_WINAPI)
     249             :   DWORD dwRetVal;
     250             :   unsigned long exitCode = -1;
     251             : 
     252             :   dwRetVal = WaitForSingleObject(process->mProcess, INFINITE);
     253             :   if (dwRetVal != WAIT_FAILED) {
     254             :     if (GetExitCodeProcess(process->mProcess, &exitCode) == FALSE) {
     255             :       exitCode = -1;
     256             :     }
     257             :   }
     258             : 
     259             :   // Lock in case Kill or GetExitCode are called during this
     260             :   {
     261             :     MutexAutoLock lock(process->mLock);
     262             :     CloseHandle(process->mProcess);
     263             :     process->mProcess = nullptr;
     264             :     process->mExitValue = exitCode;
     265             :     if (process->mShutdown) {
     266             :       return;
     267             :     }
     268             :   }
     269             : #else
     270             : #ifdef XP_MACOSX
     271             :   int exitCode = -1;
     272             :   int status = 0;
     273             :   pid_t result;
     274             :   do {
     275             :     result = waitpid(process->mPid, &status, 0);
     276             :   } while (result == -1 && errno == EINTR);
     277             :   if (result == process->mPid) {
     278             :     if (WIFEXITED(status)) {
     279             :       exitCode = WEXITSTATUS(status);
     280             :     } else if (WIFSIGNALED(status)) {
     281             :       exitCode = 256; // match NSPR's signal exit status
     282             :     }
     283             :   }
     284             : #else
     285           0 :   int32_t exitCode = -1;
     286           0 :   if (PR_WaitProcess(process->mProcess, &exitCode) != PR_SUCCESS) {
     287           0 :     exitCode = -1;
     288             :   }
     289             : #endif
     290             : 
     291             :   // Lock in case Kill or GetExitCode are called during this
     292             :   {
     293           0 :     MutexAutoLock lock(process->mLock);
     294             : #if !defined(XP_MACOSX)
     295           0 :     process->mProcess = nullptr;
     296             : #endif
     297           0 :     process->mExitValue = exitCode;
     298           0 :     if (process->mShutdown) {
     299           0 :       return;
     300             :     }
     301             :   }
     302             : #endif
     303             : 
     304             :   // If we ran a background thread for the monitor then notify on the main
     305             :   // thread
     306           0 :   if (NS_IsMainThread()) {
     307           0 :     process->ProcessComplete();
     308             :   } else {
     309           0 :     NS_DispatchToMainThread(NewRunnableMethod(
     310           0 :       "nsProcess::ProcessComplete", process, &nsProcess::ProcessComplete));
     311             :   }
     312             : 
     313           0 :   if (!process->mBlocking) {
     314           0 :     profiler_unregister_thread();
     315             :   }
     316             : }
     317             : 
     318             : void
     319           0 : nsProcess::ProcessComplete()
     320             : {
     321           0 :   if (mThread) {
     322             :     nsCOMPtr<nsIObserverService> os =
     323           0 :       mozilla::services::GetObserverService();
     324           0 :     if (os) {
     325           0 :       os->RemoveObserver(this, "xpcom-shutdown");
     326             :     }
     327           0 :     PR_JoinThread(mThread);
     328           0 :     mThread = nullptr;
     329             :   }
     330             : 
     331             :   const char* topic;
     332           0 :   if (mExitValue < 0) {
     333           0 :     topic = "process-failed";
     334             :   } else {
     335           0 :     topic = "process-finished";
     336             :   }
     337             : 
     338           0 :   mPid = -1;
     339           0 :   nsCOMPtr<nsIObserver> observer;
     340           0 :   if (mWeakObserver) {
     341           0 :     observer = do_QueryReferent(mWeakObserver);
     342           0 :   } else if (mObserver) {
     343           0 :     observer = mObserver;
     344             :   }
     345           0 :   mObserver = nullptr;
     346           0 :   mWeakObserver = nullptr;
     347             : 
     348           0 :   if (observer) {
     349           0 :     observer->Observe(NS_ISUPPORTS_CAST(nsIProcess*, this), topic, nullptr);
     350             :   }
     351           0 : }
     352             : 
     353             : // XXXldb |aArgs| has the wrong const-ness
     354             : NS_IMETHODIMP
     355           0 : nsProcess::Run(bool aBlocking, const char** aArgs, uint32_t aCount)
     356             : {
     357           0 :   return CopyArgsAndRunProcess(aBlocking, aArgs, aCount, nullptr, false);
     358             : }
     359             : 
     360             : // XXXldb |aArgs| has the wrong const-ness
     361             : NS_IMETHODIMP
     362           0 : nsProcess::RunAsync(const char** aArgs, uint32_t aCount,
     363             :                     nsIObserver* aObserver, bool aHoldWeak)
     364             : {
     365           0 :   return CopyArgsAndRunProcess(false, aArgs, aCount, aObserver, aHoldWeak);
     366             : }
     367             : 
     368             : nsresult
     369           0 : nsProcess::CopyArgsAndRunProcess(bool aBlocking, const char** aArgs,
     370             :                                  uint32_t aCount, nsIObserver* aObserver,
     371             :                                  bool aHoldWeak)
     372             : {
     373             :   // Add one to the aCount for the program name and one for null termination.
     374           0 :   char** my_argv = nullptr;
     375           0 :   my_argv = (char**)moz_xmalloc(sizeof(char*) * (aCount + 2));
     376           0 :   if (!my_argv) {
     377           0 :     return NS_ERROR_OUT_OF_MEMORY;
     378             :   }
     379             : 
     380           0 :   my_argv[0] = ToNewUTF8String(mTargetPath);
     381             : 
     382           0 :   for (uint32_t i = 0; i < aCount; ++i) {
     383           0 :     my_argv[i + 1] = const_cast<char*>(aArgs[i]);
     384             :   }
     385             : 
     386           0 :   my_argv[aCount + 1] = nullptr;
     387             : 
     388           0 :   nsresult rv = RunProcess(aBlocking, my_argv, aObserver, aHoldWeak, false);
     389             : 
     390           0 :   free(my_argv[0]);
     391           0 :   free(my_argv);
     392           0 :   return rv;
     393             : }
     394             : 
     395             : // XXXldb |aArgs| has the wrong const-ness
     396             : NS_IMETHODIMP
     397           0 : nsProcess::Runw(bool aBlocking, const char16_t** aArgs, uint32_t aCount)
     398             : {
     399           0 :   return CopyArgsAndRunProcessw(aBlocking, aArgs, aCount, nullptr, false);
     400             : }
     401             : 
     402             : // XXXldb |aArgs| has the wrong const-ness
     403             : NS_IMETHODIMP
     404           0 : nsProcess::RunwAsync(const char16_t** aArgs, uint32_t aCount,
     405             :                      nsIObserver* aObserver, bool aHoldWeak)
     406             : {
     407           0 :   return CopyArgsAndRunProcessw(false, aArgs, aCount, aObserver, aHoldWeak);
     408             : }
     409             : 
     410             : nsresult
     411           0 : nsProcess::CopyArgsAndRunProcessw(bool aBlocking, const char16_t** aArgs,
     412             :                                   uint32_t aCount, nsIObserver* aObserver,
     413             :                                   bool aHoldWeak)
     414             : {
     415             :   // Add one to the aCount for the program name and one for null termination.
     416           0 :   char** my_argv = nullptr;
     417           0 :   my_argv = (char**)moz_xmalloc(sizeof(char*) * (aCount + 2));
     418           0 :   if (!my_argv) {
     419           0 :     return NS_ERROR_OUT_OF_MEMORY;
     420             :   }
     421             : 
     422           0 :   my_argv[0] = ToNewUTF8String(mTargetPath);
     423             : 
     424           0 :   for (uint32_t i = 0; i < aCount; i++) {
     425           0 :     my_argv[i + 1] = ToNewUTF8String(nsDependentString(aArgs[i]));
     426             :   }
     427             : 
     428           0 :   my_argv[aCount + 1] = nullptr;
     429             : 
     430           0 :   nsresult rv = RunProcess(aBlocking, my_argv, aObserver, aHoldWeak, true);
     431             : 
     432           0 :   for (uint32_t i = 0; i <= aCount; ++i) {
     433           0 :     free(my_argv[i]);
     434             :   }
     435           0 :   free(my_argv);
     436           0 :   return rv;
     437             : }
     438             : 
     439             : nsresult
     440           0 : nsProcess::RunProcess(bool aBlocking, char** aMyArgv, nsIObserver* aObserver,
     441             :                       bool aHoldWeak, bool aArgsUTF8)
     442             : {
     443           0 :   NS_WARNING_ASSERTION(!XRE_IsContentProcess(),
     444             :                        "No launching of new processes in the content process");
     445             : 
     446           0 :   if (NS_WARN_IF(!mExecutable)) {
     447           0 :     return NS_ERROR_NOT_INITIALIZED;
     448             :   }
     449           0 :   if (NS_WARN_IF(mThread)) {
     450           0 :     return NS_ERROR_ALREADY_INITIALIZED;
     451             :   }
     452             : 
     453           0 :   if (aObserver) {
     454           0 :     if (aHoldWeak) {
     455           0 :       mWeakObserver = do_GetWeakReference(aObserver);
     456           0 :       if (!mWeakObserver) {
     457           0 :         return NS_NOINTERFACE;
     458             :       }
     459             :     } else {
     460           0 :       mObserver = aObserver;
     461             :     }
     462             :   }
     463             : 
     464           0 :   mExitValue = -1;
     465           0 :   mPid = -1;
     466             : 
     467             : #if defined(PROCESSMODEL_WINAPI)
     468             :   BOOL retVal;
     469             :   wchar_t* cmdLine = nullptr;
     470             : 
     471             :   // |aMyArgv| is null-terminated and always starts with the program path. If
     472             :   // the second slot is non-null then arguments are being passed.
     473             :   if (aMyArgv[1] && assembleCmdLine(aMyArgv + 1, &cmdLine,
     474             :                                     aArgsUTF8 ? CP_UTF8 : CP_ACP) == -1) {
     475             :     return NS_ERROR_FILE_EXECUTION_FAILED;
     476             :   }
     477             : 
     478             :   /* The SEE_MASK_NO_CONSOLE flag is important to prevent console windows
     479             :    * from appearing. This makes behavior the same on all platforms. The flag
     480             :    * will not have any effect on non-console applications.
     481             :    */
     482             : 
     483             :   // The program name in aMyArgv[0] is always UTF-8
     484             :   NS_ConvertUTF8toUTF16 wideFile(aMyArgv[0]);
     485             : 
     486             :   SHELLEXECUTEINFOW sinfo;
     487             :   memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW));
     488             :   sinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
     489             :   sinfo.hwnd   = nullptr;
     490             :   sinfo.lpFile = wideFile.get();
     491             :   sinfo.nShow  = mStartHidden ? SW_HIDE : SW_SHOWNORMAL;
     492             :   sinfo.fMask  = SEE_MASK_FLAG_DDEWAIT |
     493             :                  SEE_MASK_NO_CONSOLE |
     494             :                  SEE_MASK_NOCLOSEPROCESS;
     495             : 
     496             :   if (cmdLine) {
     497             :     sinfo.lpParameters = cmdLine;
     498             :   }
     499             : 
     500             :   retVal = ShellExecuteExW(&sinfo);
     501             :   if (!retVal) {
     502             :     return NS_ERROR_FILE_EXECUTION_FAILED;
     503             :   }
     504             : 
     505             :   mProcess = sinfo.hProcess;
     506             : 
     507             :   if (cmdLine) {
     508             :     free(cmdLine);
     509             :   }
     510             : 
     511             :   mPid = GetProcessId(mProcess);
     512             : #elif defined(XP_MACOSX)
     513             :   // Initialize spawn attributes.
     514             :   posix_spawnattr_t spawnattr;
     515             :   if (posix_spawnattr_init(&spawnattr) != 0) {
     516             :     return NS_ERROR_FAILURE;
     517             :   }
     518             : 
     519             :   // Set spawn attributes.
     520             :   size_t attr_count = ArrayLength(pref_cpu_types);
     521             :   size_t attr_ocount = 0;
     522             :   if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, pref_cpu_types,
     523             :                                     &attr_ocount) != 0 ||
     524             :       attr_ocount != attr_count) {
     525             :     posix_spawnattr_destroy(&spawnattr);
     526             :     return NS_ERROR_FAILURE;
     527             :   }
     528             : 
     529             :   // Note: |aMyArgv| is already null-terminated as required by posix_spawnp.
     530             :   pid_t newPid = 0;
     531             :   int result = posix_spawnp(&newPid, aMyArgv[0], nullptr, &spawnattr, aMyArgv,
     532             :                             *_NSGetEnviron());
     533             :   mPid = static_cast<int32_t>(newPid);
     534             : 
     535             :   posix_spawnattr_destroy(&spawnattr);
     536             : 
     537             :   if (result != 0) {
     538             :     return NS_ERROR_FAILURE;
     539             :   }
     540             : #else
     541           0 :   mProcess = PR_CreateProcess(aMyArgv[0], aMyArgv, nullptr, nullptr);
     542           0 :   if (!mProcess) {
     543           0 :     return NS_ERROR_FAILURE;
     544             :   }
     545             :   struct MYProcess
     546             :   {
     547             :     uint32_t pid;
     548             :   };
     549           0 :   MYProcess* ptrProc = (MYProcess*)mProcess;
     550           0 :   mPid = ptrProc->pid;
     551             : #endif
     552             : 
     553           0 :   NS_ADDREF_THIS();
     554           0 :   mBlocking = aBlocking;
     555           0 :   if (aBlocking) {
     556           0 :     Monitor(this);
     557           0 :     if (mExitValue < 0) {
     558           0 :       return NS_ERROR_FILE_EXECUTION_FAILED;
     559             :     }
     560             :   } else {
     561           0 :     mThread = PR_CreateThread(PR_SYSTEM_THREAD, Monitor, this,
     562             :                               PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
     563             :                               PR_JOINABLE_THREAD, 0);
     564           0 :     if (!mThread) {
     565           0 :       NS_RELEASE_THIS();
     566           0 :       return NS_ERROR_FAILURE;
     567             :     }
     568             : 
     569             :     // It isn't a failure if we just can't watch for shutdown
     570             :     nsCOMPtr<nsIObserverService> os =
     571           0 :       mozilla::services::GetObserverService();
     572           0 :     if (os) {
     573           0 :       os->AddObserver(this, "xpcom-shutdown", false);
     574             :     }
     575             :   }
     576             : 
     577           0 :   return NS_OK;
     578             : }
     579             : 
     580             : NS_IMETHODIMP
     581           0 : nsProcess::GetIsRunning(bool* aIsRunning)
     582             : {
     583           0 :   if (mThread) {
     584           0 :     *aIsRunning = true;
     585             :   } else {
     586           0 :     *aIsRunning = false;
     587             :   }
     588             : 
     589           0 :   return NS_OK;
     590             : }
     591             : 
     592             : NS_IMETHODIMP
     593           0 : nsProcess::GetStartHidden(bool* aStartHidden)
     594             : {
     595           0 :   *aStartHidden = mStartHidden;
     596           0 :   return NS_OK;
     597             : }
     598             : 
     599             : NS_IMETHODIMP
     600           0 : nsProcess::SetStartHidden(bool aStartHidden)
     601             : {
     602           0 :   mStartHidden = aStartHidden;
     603           0 :   return NS_OK;
     604             : }
     605             : 
     606             : NS_IMETHODIMP
     607           0 : nsProcess::GetPid(uint32_t* aPid)
     608             : {
     609           0 :   if (!mThread) {
     610           0 :     return NS_ERROR_FAILURE;
     611             :   }
     612           0 :   if (mPid < 0) {
     613           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     614             :   }
     615           0 :   *aPid = mPid;
     616           0 :   return NS_OK;
     617             : }
     618             : 
     619             : NS_IMETHODIMP
     620           0 : nsProcess::Kill()
     621             : {
     622           0 :   if (!mThread) {
     623           0 :     return NS_ERROR_FAILURE;
     624             :   }
     625             : 
     626             :   {
     627           0 :     MutexAutoLock lock(mLock);
     628             : #if defined(PROCESSMODEL_WINAPI)
     629             :     if (TerminateProcess(mProcess, 0) == 0) {
     630             :       return NS_ERROR_FAILURE;
     631             :     }
     632             : #elif defined(XP_MACOSX)
     633             :     if (kill(mPid, SIGKILL) != 0) {
     634             :       return NS_ERROR_FAILURE;
     635             :     }
     636             : #else
     637           0 :     if (!mProcess || (PR_KillProcess(mProcess) != PR_SUCCESS)) {
     638           0 :       return NS_ERROR_FAILURE;
     639             :     }
     640             : #endif
     641             :   }
     642             : 
     643             :   // We must null out mThread if we want IsRunning to return false immediately
     644             :   // after this call.
     645           0 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     646           0 :   if (os) {
     647           0 :     os->RemoveObserver(this, "xpcom-shutdown");
     648             :   }
     649           0 :   PR_JoinThread(mThread);
     650           0 :   mThread = nullptr;
     651             : 
     652           0 :   return NS_OK;
     653             : }
     654             : 
     655             : NS_IMETHODIMP
     656           0 : nsProcess::GetExitValue(int32_t* aExitValue)
     657             : {
     658           0 :   MutexAutoLock lock(mLock);
     659             : 
     660           0 :   *aExitValue = mExitValue;
     661             : 
     662           0 :   return NS_OK;
     663             : }
     664             : 
     665             : NS_IMETHODIMP
     666           0 : nsProcess::Observe(nsISupports* aSubject, const char* aTopic,
     667             :                    const char16_t* aData)
     668             : {
     669             :   // Shutting down, drop all references
     670           0 :   if (mThread) {
     671             :     nsCOMPtr<nsIObserverService> os =
     672           0 :       mozilla::services::GetObserverService();
     673           0 :     if (os) {
     674           0 :       os->RemoveObserver(this, "xpcom-shutdown");
     675             :     }
     676           0 :     mThread = nullptr;
     677             :   }
     678             : 
     679           0 :   mObserver = nullptr;
     680           0 :   mWeakObserver = nullptr;
     681             : 
     682           0 :   MutexAutoLock lock(mLock);
     683           0 :   mShutdown = true;
     684             : 
     685           0 :   return NS_OK;
     686             : }

Generated by: LCOV version 1.13