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 |