| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "base/process/kill.h" | 5 #include "base/process/kill.h" | 
| 6 | 6 | 
| 7 #include <signal.h> | 7 #include <signal.h> | 
| 8 #include <sys/types.h> | 8 #include <sys/types.h> | 
| 9 #include <sys/wait.h> | 9 #include <sys/wait.h> | 
| 10 #include <unistd.h> | 10 #include <unistd.h> | 
| 11 | 11 | 
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" | 
| 13 #include "base/files/scoped_file.h" | 13 #include "base/files/scoped_file.h" | 
| 14 #include "base/logging.h" | 14 #include "base/logging.h" | 
| 15 #include "base/posix/eintr_wrapper.h" | 15 #include "base/posix/eintr_wrapper.h" | 
| 16 #include "base/process/process_iterator.h" | 16 #include "base/process/process_iterator.h" | 
| 17 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" | 
| 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 
| 19 #include "base/threading/platform_thread.h" | 19 #include "base/threading/platform_thread.h" | 
| 20 | 20 | 
| 21 namespace base { | 21 namespace base { | 
| 22 | 22 | 
| 23 namespace { | 23 namespace { | 
| 24 | 24 | 
|  | 25 #if !defined(__native_client_nonsfi__) | 
| 25 bool WaitpidWithTimeout(ProcessHandle handle, | 26 bool WaitpidWithTimeout(ProcessHandle handle, | 
| 26                         int* status, | 27                         int* status, | 
| 27                         base::TimeDelta wait) { | 28                         base::TimeDelta wait) { | 
| 28   // This POSIX version of this function only guarantees that we wait no less | 29   // This POSIX version of this function only guarantees that we wait no less | 
| 29   // than |wait| for the process to exit.  The child process may | 30   // than |wait| for the process to exit.  The child process may | 
| 30   // exit sometime before the timeout has ended but we may still block for up | 31   // exit sometime before the timeout has ended but we may still block for up | 
| 31   // to 256 milliseconds after the fact. | 32   // to 256 milliseconds after the fact. | 
| 32   // | 33   // | 
| 33   // waitpid() has no direct support on POSIX for specifying a timeout, you can | 34   // waitpid() has no direct support on POSIX for specifying a timeout, you can | 
| 34   // either ask it to block indefinitely or return immediately (WNOHANG). | 35   // either ask it to block indefinitely or return immediately (WNOHANG). | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 76     ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG)); | 77     ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG)); | 
| 77 | 78 | 
| 78     if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) && | 79     if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) && | 
| 79         (double_sleep_time++ % 4 == 0)) { | 80         (double_sleep_time++ % 4 == 0)) { | 
| 80       max_sleep_time_usecs *= 2; | 81       max_sleep_time_usecs *= 2; | 
| 81     } | 82     } | 
| 82   } | 83   } | 
| 83 | 84 | 
| 84   return ret_pid > 0; | 85   return ret_pid > 0; | 
| 85 } | 86 } | 
|  | 87 #endif  // !defined(__native_client_nonsfi__) | 
| 86 | 88 | 
| 87 TerminationStatus GetTerminationStatusImpl(ProcessHandle handle, | 89 TerminationStatus GetTerminationStatusImpl(ProcessHandle handle, | 
| 88                                            bool can_block, | 90                                            bool can_block, | 
| 89                                            int* exit_code) { | 91                                            int* exit_code) { | 
| 90   int status = 0; | 92   int status = 0; | 
| 91   const pid_t result = HANDLE_EINTR(waitpid(handle, &status, | 93   const pid_t result = HANDLE_EINTR(waitpid(handle, &status, | 
| 92                                             can_block ? 0 : WNOHANG)); | 94                                             can_block ? 0 : WNOHANG)); | 
| 93   if (result == -1) { | 95   if (result == -1) { | 
| 94     DPLOG(ERROR) << "waitpid(" << handle << ")"; | 96     DPLOG(ERROR) << "waitpid(" << handle << ")"; | 
| 95     if (exit_code) | 97     if (exit_code) | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 123   } | 125   } | 
| 124 | 126 | 
| 125   if (WIFEXITED(status) && WEXITSTATUS(status) != 0) | 127   if (WIFEXITED(status) && WEXITSTATUS(status) != 0) | 
| 126     return TERMINATION_STATUS_ABNORMAL_TERMINATION; | 128     return TERMINATION_STATUS_ABNORMAL_TERMINATION; | 
| 127 | 129 | 
| 128   return TERMINATION_STATUS_NORMAL_TERMINATION; | 130   return TERMINATION_STATUS_NORMAL_TERMINATION; | 
| 129 } | 131 } | 
| 130 | 132 | 
| 131 }  // namespace | 133 }  // namespace | 
| 132 | 134 | 
|  | 135 #if !defined(__native_client_nonsfi__) | 
| 133 // Attempts to kill the process identified by the given process | 136 // Attempts to kill the process identified by the given process | 
| 134 // entry structure.  Ignores specified exit_code; posix can't force that. | 137 // entry structure.  Ignores specified exit_code; posix can't force that. | 
| 135 // Returns true if this is successful, false otherwise. | 138 // Returns true if this is successful, false otherwise. | 
| 136 bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) { | 139 bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) { | 
| 137   DCHECK_GT(process_id, 1) << " tried to kill invalid process_id"; | 140   DCHECK_GT(process_id, 1) << " tried to kill invalid process_id"; | 
| 138   if (process_id <= 1) | 141   if (process_id <= 1) | 
| 139     return false; | 142     return false; | 
| 140   bool result = kill(process_id, SIGTERM) == 0; | 143   bool result = kill(process_id, SIGTERM) == 0; | 
| 141   if (result && wait) { | 144   if (result && wait) { | 
| 142     int tries = 60; | 145     int tries = 60; | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 184 | 187 | 
| 185   return result; | 188   return result; | 
| 186 } | 189 } | 
| 187 | 190 | 
| 188 bool KillProcessGroup(ProcessHandle process_group_id) { | 191 bool KillProcessGroup(ProcessHandle process_group_id) { | 
| 189   bool result = kill(-1 * process_group_id, SIGKILL) == 0; | 192   bool result = kill(-1 * process_group_id, SIGKILL) == 0; | 
| 190   if (!result) | 193   if (!result) | 
| 191     DPLOG(ERROR) << "Unable to terminate process group " << process_group_id; | 194     DPLOG(ERROR) << "Unable to terminate process group " << process_group_id; | 
| 192   return result; | 195   return result; | 
| 193 } | 196 } | 
|  | 197 #endif  // !defined(__native_client_nonsfi__) | 
| 194 | 198 | 
| 195 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { | 199 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { | 
| 196   return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); | 200   return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); | 
| 197 } | 201 } | 
| 198 | 202 | 
| 199 TerminationStatus GetKnownDeadTerminationStatus(ProcessHandle handle, | 203 TerminationStatus GetKnownDeadTerminationStatus(ProcessHandle handle, | 
| 200                                                 int* exit_code) { | 204                                                 int* exit_code) { | 
| 201   bool result = kill(handle, SIGKILL) == 0; | 205   bool result = kill(handle, SIGKILL) == 0; | 
| 202 | 206 | 
| 203   if (!result) | 207   if (!result) | 
| 204     DPLOG(ERROR) << "Unable to terminate process " << handle; | 208     DPLOG(ERROR) << "Unable to terminate process " << handle; | 
| 205 | 209 | 
| 206   return GetTerminationStatusImpl(handle, true /* can_block */, exit_code); | 210   return GetTerminationStatusImpl(handle, true /* can_block */, exit_code); | 
| 207 } | 211 } | 
| 208 | 212 | 
|  | 213 #if !defined(__native_client_nonsfi__) | 
| 209 bool WaitForExitCode(ProcessHandle handle, int* exit_code) { | 214 bool WaitForExitCode(ProcessHandle handle, int* exit_code) { | 
| 210   int status; | 215   int status; | 
| 211   if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) { | 216   if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) { | 
| 212     NOTREACHED(); | 217     NOTREACHED(); | 
| 213     return false; | 218     return false; | 
| 214   } | 219   } | 
| 215 | 220 | 
| 216   if (WIFEXITED(status)) { | 221   if (WIFEXITED(status)) { | 
| 217     *exit_code = WEXITSTATUS(status); | 222     *exit_code = WEXITSTATUS(status); | 
| 218     return true; | 223     return true; | 
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 471 void EnsureProcessGetsReaped(ProcessHandle process) { | 476 void EnsureProcessGetsReaped(ProcessHandle process) { | 
| 472   // If the child is already dead, then there's nothing to do. | 477   // If the child is already dead, then there's nothing to do. | 
| 473   if (IsChildDead(process)) | 478   if (IsChildDead(process)) | 
| 474     return; | 479     return; | 
| 475 | 480 | 
| 476   BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 481   BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 
| 477   PlatformThread::CreateNonJoinable(0, reaper); | 482   PlatformThread::CreateNonJoinable(0, reaper); | 
| 478 } | 483 } | 
| 479 | 484 | 
| 480 #endif  // !defined(OS_MACOSX) | 485 #endif  // !defined(OS_MACOSX) | 
|  | 486 #endif  // !defined(__native_client_nonsfi__) | 
| 481 | 487 | 
| 482 }  // namespace base | 488 }  // namespace base | 
| OLD | NEW | 
|---|