OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <dirent.h> | 5 #include <dirent.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <signal.h> | 8 #include <signal.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <sys/resource.h> | 10 #include <sys/resource.h> |
(...skipping 1192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1203 int exit_code, | 1203 int exit_code, |
1204 const ProcessFilter* filter) { | 1204 const ProcessFilter* filter) { |
1205 bool exited_cleanly = | 1205 bool exited_cleanly = |
1206 WaitForProcessesToExit(executable_name, wait_milliseconds, | 1206 WaitForProcessesToExit(executable_name, wait_milliseconds, |
1207 filter); | 1207 filter); |
1208 if (!exited_cleanly) | 1208 if (!exited_cleanly) |
1209 KillProcesses(executable_name, exit_code, filter); | 1209 KillProcesses(executable_name, exit_code, filter); |
1210 return exited_cleanly; | 1210 return exited_cleanly; |
1211 } | 1211 } |
1212 | 1212 |
1213 #if !defined(OS_MACOSX) | |
1214 | |
1215 namespace { | |
1216 | |
1217 // Return true if the given child is dead. This will also reap the process. | |
1218 // Doesn't block. | |
1219 static bool IsChildDead(pid_t child) { | |
1220 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG)); | |
1221 if (result == -1) { | |
1222 DPLOG(ERROR) << "waitpid(" << child << ")"; | |
1223 NOTREACHED(); | |
1224 } else if (result > 0) { | |
1225 // The child has died. | |
1226 return true; | |
1227 } | |
1228 | |
1229 return false; | |
1230 } | |
1231 | |
1232 // A thread class which waits for the given child to exit and reaps it. | |
1233 // If the child doesn't exit within a couple of seconds, kill it. | |
1234 class BackgroundReaper : public PlatformThread::Delegate { | |
1235 public: | |
1236 BackgroundReaper(pid_t child, unsigned timeout) | |
1237 : child_(child), | |
1238 timeout_(timeout) { | |
1239 } | |
1240 | |
1241 void ThreadMain() { | |
1242 WaitForChildToDie(); | |
1243 delete this; | |
1244 } | |
1245 | |
1246 void WaitForChildToDie() { | |
1247 // Wait forever case. | |
1248 if (timeout_ == 0) { | |
1249 pid_t r = HANDLE_EINTR(waitpid(child_, NULL, 0)); | |
1250 if (r != child_) { | |
1251 DPLOG(ERROR) << "While waiting for " << child_ | |
1252 << " to terminate, we got the following result: " << r; | |
1253 } | |
1254 return; | |
1255 } | |
1256 | |
1257 // There's no good way to wait for a specific child to exit in a timed | |
1258 // fashion. (No kqueue on Linux), so we just loop and sleep. | |
1259 | |
1260 // Wait for 2 * timeout_ 500 milliseconds intervals. | |
1261 for (unsigned i = 0; i < 2 * timeout_; ++i) { | |
1262 PlatformThread::Sleep(500); // 0.5 seconds | |
1263 if (IsChildDead(child_)) | |
1264 return; | |
1265 } | |
1266 | |
1267 if (kill(child_, SIGKILL) == 0) { | |
1268 // SIGKILL is uncatchable. Since the signal was delivered, we can | |
1269 // just wait for the process to die now in a blocking manner. | |
1270 if (HANDLE_EINTR(waitpid(child_, NULL, 0)) < 0) | |
1271 DPLOG(WARNING) << "waitpid"; | |
1272 } else { | |
1273 DLOG(ERROR) << "While waiting for " << child_ << " to terminate we" | |
1274 << " failed to deliver a SIGKILL signal (" << errno << ")."; | |
1275 } | |
1276 } | |
1277 | |
1278 private: | |
1279 const pid_t child_; | |
1280 // Number of seconds to wait, if 0 then wait forever and do not attempt to | |
1281 // kill |child_|. | |
1282 const unsigned timeout_; | |
1283 | |
1284 DISALLOW_COPY_AND_ASSIGN(BackgroundReaper); | |
1285 }; | |
1286 | |
1287 } // namespace | |
1288 | |
1289 void EnsureProcessTerminated(ProcessHandle process) { | |
1290 // If the child is already dead, then there's nothing to do. | |
1291 if (IsChildDead(process)) | |
1292 return; | |
1293 | |
1294 const unsigned timeout = 2; // seconds | |
1295 BackgroundReaper* reaper = new BackgroundReaper(process, timeout); | |
1296 PlatformThread::CreateNonJoinable(0, reaper); | |
1297 } | |
1298 | |
1299 void EnsureProcessGetsReaped(ProcessHandle process) { | |
1300 // If the child is already dead, then there's nothing to do. | |
1301 if (IsChildDead(process)) | |
1302 return; | |
1303 | |
1304 BackgroundReaper* reaper = new BackgroundReaper(process, 0); | |
1305 PlatformThread::CreateNonJoinable(0, reaper); | |
1306 } | |
1307 | |
1308 #endif | |
willchan no longer on Chromium
2011/11/23 17:46:37
Up to you, but it's my personal preference to term
jam
2011/11/23 17:48:33
Done.
| |
1309 | |
1213 } // namespace base | 1310 } // namespace base |
OLD | NEW |