1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/kill.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <errno.h> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <signal.h> 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/types.h> 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/wait.h> 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <unistd.h> 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/files/file_util.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/files/scoped_file.h" 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 16cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/macros.h" 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/posix/eintr_wrapper.h" 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/process_iterator.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/waitable_event.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/platform_thread.h" 21cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTerminationStatus GetTerminationStatusImpl(ProcessHandle handle, 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool can_block, 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int* exit_code) { 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int status = 0; 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const pid_t result = HANDLE_EINTR(waitpid(handle, &status, 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat can_block ? 0 : WNOHANG)); 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (result == -1) { 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "waitpid(" << handle << ")"; 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (exit_code) 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *exit_code = 0; 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_NORMAL_TERMINATION; 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else if (result == 0) { 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the child hasn't exited yet. 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (exit_code) 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *exit_code = 0; 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_STILL_RUNNING; 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (exit_code) 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *exit_code = status; 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (WIFSIGNALED(status)) { 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switch (WTERMSIG(status)) { 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGABRT: 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGBUS: 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGFPE: 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGILL: 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGSEGV: 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_PROCESS_CRASHED; 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGKILL: 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_CHROMEOS) 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // On ChromeOS, only way a process gets kill by SIGKILL 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // is by oom-killer. 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM; 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGINT: 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SIGTERM: 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_PROCESS_WAS_KILLED; 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat default: 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat break; 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (WIFEXITED(status) && WEXITSTATUS(status) != 0) 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_ABNORMAL_TERMINATION; 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TERMINATION_STATUS_NORMAL_TERMINATION; 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if !defined(OS_NACL_NONSFI) 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool KillProcessGroup(ProcessHandle process_group_id) { 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool result = kill(-1 * process_group_id, SIGKILL) == 0; 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!result) 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "Unable to terminate process group " << process_group_id; 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return result; 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // !defined(OS_NACL_NONSFI) 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTerminationStatus GetKnownDeadTerminationStatus(ProcessHandle handle, 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int* exit_code) { 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool result = kill(handle, SIGKILL) == 0; 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!result) 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "Unable to terminate process " << handle; 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return GetTerminationStatusImpl(handle, true /* can_block */, exit_code); 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if !defined(OS_NACL_NONSFI) 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool WaitForProcessesToExit(const FilePath::StringType& executable_name, 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeDelta wait, 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ProcessFilter* filter) { 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool result = false; 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TODO(port): This is inefficient, but works if there are multiple procs. 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TODO(port): use waitpid to avoid leaving zombies around 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeTicks end_time = TimeTicks::Now() + wait; 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat do { 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NamedProcessIterator iter(executable_name, filter); 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!iter.NextProcessEntry()) { 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat result = true; 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat break; 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } while ((end_time - TimeTicks::Now()) > TimeDelta()); 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return result; 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool CleanupProcesses(const FilePath::StringType& executable_name, 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TimeDelta wait, 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int exit_code, 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ProcessFilter* filter) { 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool exited_cleanly = WaitForProcessesToExit(executable_name, wait, filter); 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!exited_cleanly) 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat KillProcesses(executable_name, exit_code, filter); 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return exited_cleanly; 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if !defined(OS_MACOSX) 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Return true if the given child is dead. This will also reap the process. 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Doesn't block. 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic bool IsChildDead(pid_t child) { 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG)); 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (result == -1) { 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "waitpid(" << child << ")"; 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else if (result > 0) { 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The child has died. 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// A thread class which waits for the given child to exit and reaps it. 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// If the child doesn't exit within a couple of seconds, kill it. 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BackgroundReaper : public PlatformThread::Delegate { 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundReaper(pid_t child, unsigned timeout) 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : child_(child), 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat timeout_(timeout) { 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Overridden from PlatformThread::Delegate: 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void ThreadMain() override { 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WaitForChildToDie(); 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete this; 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void WaitForChildToDie() { 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Wait forever case. 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (timeout_ == 0) { 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pid_t r = HANDLE_EINTR(waitpid(child_, NULL, 0)); 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (r != child_) { 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(ERROR) << "While waiting for " << child_ 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat << " to terminate, we got the following result: " << r; 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // There's no good way to wait for a specific child to exit in a timed 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // fashion. (No kqueue on Linux), so we just loop and sleep. 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Wait for 2 * timeout_ 500 milliseconds intervals. 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (unsigned i = 0; i < 2 * timeout_; ++i) { 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (IsChildDead(child_)) 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (kill(child_, SIGKILL) == 0) { 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // SIGKILL is uncatchable. Since the signal was delivered, we can 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // just wait for the process to die now in a blocking manner. 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (HANDLE_EINTR(waitpid(child_, NULL, 0)) < 0) 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DPLOG(WARNING) << "waitpid"; 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(ERROR) << "While waiting for " << child_ << " to terminate we" 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat << " failed to deliver a SIGKILL signal (" << errno << ")."; 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const pid_t child_; 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Number of seconds to wait, if 0 then wait forever and do not attempt to 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // kill |child_|. 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const unsigned timeout_; 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISALLOW_COPY_AND_ASSIGN(BackgroundReaper); 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid EnsureProcessTerminated(Process process) { 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // If the child is already dead, then there's nothing to do. 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (IsChildDead(process.Pid())) 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const unsigned timeout = 2; // seconds 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundReaper* reaper = new BackgroundReaper(process.Pid(), timeout); 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PlatformThread::CreateNonJoinable(0, reaper); 218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid EnsureProcessGetsReaped(ProcessId pid) { 221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // If the child is already dead, then there's nothing to do. 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (IsChildDead(pid)) 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundReaper* reaper = new BackgroundReaper(pid, 0); 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PlatformThread::CreateNonJoinable(0, reaper); 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // !defined(OS_MACOSX) 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // !defined(OS_NACL_NONSFI) 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 233