OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 *exit_code = WEXITSTATUS(status); | 879 *exit_code = WEXITSTATUS(status); |
880 return true; | 880 return true; |
881 } | 881 } |
882 | 882 |
883 // If it didn't exit cleanly, it must have been signaled. | 883 // If it didn't exit cleanly, it must have been signaled. |
884 DCHECK(WIFSIGNALED(status)); | 884 DCHECK(WIFSIGNALED(status)); |
885 return false; | 885 return false; |
886 } | 886 } |
887 | 887 |
888 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, | 888 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, |
889 int64 timeout_milliseconds) { | 889 base::TimeDelta timeout) { |
890 bool waitpid_success = false; | 890 bool waitpid_success = false; |
891 int status = WaitpidWithTimeout(handle, timeout_milliseconds, | 891 int status = WaitpidWithTimeout(handle, timeout.InMilliseconds(), |
892 &waitpid_success); | 892 &waitpid_success); |
893 if (status == -1) | 893 if (status == -1) |
894 return false; | 894 return false; |
895 if (!waitpid_success) | 895 if (!waitpid_success) |
896 return false; | 896 return false; |
897 if (WIFSIGNALED(status)) { | 897 if (WIFSIGNALED(status)) { |
898 *exit_code = -1; | 898 *exit_code = -1; |
899 return true; | 899 return true; |
900 } | 900 } |
901 if (WIFEXITED(status)) { | 901 if (WIFEXITED(status)) { |
902 *exit_code = WEXITSTATUS(status); | 902 *exit_code = WEXITSTATUS(status); |
903 return true; | 903 return true; |
904 } | 904 } |
905 return false; | 905 return false; |
906 } | 906 } |
907 | 907 |
908 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, | |
909 base::TimeDelta timeout) { | |
910 return WaitForExitCodeWithTimeout( | |
911 handle, exit_code, timeout.InMilliseconds()); | |
912 } | |
913 | |
914 #if defined(OS_MACOSX) | 908 #if defined(OS_MACOSX) |
915 // Using kqueue on Mac so that we can wait on non-child processes. | 909 // Using kqueue on Mac so that we can wait on non-child processes. |
916 // We can't use kqueues on child processes because we need to reap | 910 // We can't use kqueues on child processes because we need to reap |
917 // our own children using wait. | 911 // our own children using wait. |
918 static bool WaitForSingleNonChildProcess(ProcessHandle handle, | 912 static bool WaitForSingleNonChildProcess(ProcessHandle handle, |
919 base::TimeDelta wait) { | 913 base::TimeDelta wait) { |
920 DCHECK_GT(handle, 0); | 914 DCHECK_GT(handle, 0); |
921 DCHECK(wait.InMilliseconds() == base::kNoTimeout || wait > base::TimeDelta()); | 915 DCHECK(wait.InMilliseconds() == base::kNoTimeout || wait > base::TimeDelta()); |
922 | 916 |
923 int kq = kqueue(); | 917 int kq = kqueue(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 << "): unexpected event: filter=" << event.filter | 990 << "): unexpected event: filter=" << event.filter |
997 << ", fflags=" << event.fflags | 991 << ", fflags=" << event.fflags |
998 << ", ident=" << event.ident; | 992 << ", ident=" << event.ident; |
999 return false; | 993 return false; |
1000 } | 994 } |
1001 | 995 |
1002 return true; | 996 return true; |
1003 } | 997 } |
1004 #endif // OS_MACOSX | 998 #endif // OS_MACOSX |
1005 | 999 |
1006 bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) { | |
1007 return WaitForSingleProcess( | |
1008 handle, base::TimeDelta::FromMilliseconds(wait_milliseconds)); | |
1009 } | |
1010 | |
1011 bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) { | 1000 bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) { |
1012 ProcessHandle parent_pid = GetParentProcessId(handle); | 1001 ProcessHandle parent_pid = GetParentProcessId(handle); |
1013 ProcessHandle our_pid = Process::Current().handle(); | 1002 ProcessHandle our_pid = Process::Current().handle(); |
1014 if (parent_pid != our_pid) { | 1003 if (parent_pid != our_pid) { |
1015 #if defined(OS_MACOSX) | 1004 #if defined(OS_MACOSX) |
1016 // On Mac we can wait on non child processes. | 1005 // On Mac we can wait on non child processes. |
1017 return WaitForSingleNonChildProcess(handle, wait); | 1006 return WaitForSingleNonChildProcess(handle, wait); |
1018 #else | 1007 #else |
1019 // Currently on Linux we can't handle non child processes. | 1008 // Currently on Linux we can't handle non child processes. |
1020 NOTIMPLEMENTED(); | 1009 NOTIMPLEMENTED(); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 std::string* output, | 1199 std::string* output, |
1211 int* exit_code) { | 1200 int* exit_code) { |
1212 // Run |execve()| with the current environment and store "unlimited" data. | 1201 // Run |execve()| with the current environment and store "unlimited" data. |
1213 GetAppOutputInternalResult result = GetAppOutputInternal( | 1202 GetAppOutputInternalResult result = GetAppOutputInternal( |
1214 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 1203 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
1215 exit_code); | 1204 exit_code); |
1216 return result == EXECUTE_SUCCESS; | 1205 return result == EXECUTE_SUCCESS; |
1217 } | 1206 } |
1218 | 1207 |
1219 bool WaitForProcessesToExit(const FilePath::StringType& executable_name, | 1208 bool WaitForProcessesToExit(const FilePath::StringType& executable_name, |
1220 int64 wait_milliseconds, | 1209 base::TimeDelta wait, |
1221 const ProcessFilter* filter) { | 1210 const ProcessFilter* filter) { |
1222 bool result = false; | 1211 bool result = false; |
1223 | 1212 |
1224 // TODO(port): This is inefficient, but works if there are multiple procs. | 1213 // TODO(port): This is inefficient, but works if there are multiple procs. |
1225 // TODO(port): use waitpid to avoid leaving zombies around | 1214 // TODO(port): use waitpid to avoid leaving zombies around |
1226 | 1215 |
1227 base::Time end_time = base::Time::Now() + | 1216 base::Time end_time = base::Time::Now() + wait; |
1228 base::TimeDelta::FromMilliseconds(wait_milliseconds); | |
1229 do { | 1217 do { |
1230 NamedProcessIterator iter(executable_name, filter); | 1218 NamedProcessIterator iter(executable_name, filter); |
1231 if (!iter.NextProcessEntry()) { | 1219 if (!iter.NextProcessEntry()) { |
1232 result = true; | 1220 result = true; |
1233 break; | 1221 break; |
1234 } | 1222 } |
1235 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 1223 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
1236 } while ((end_time - base::Time::Now()) > base::TimeDelta()); | 1224 } while ((end_time - base::Time::Now()) > base::TimeDelta()); |
1237 | 1225 |
1238 return result; | 1226 return result; |
1239 } | 1227 } |
1240 | 1228 |
1241 bool WaitForProcessesToExit(const FilePath::StringType& executable_name, | |
1242 base::TimeDelta wait, | |
1243 const ProcessFilter* filter) { | |
1244 return WaitForProcessesToExit(executable_name, wait.InMilliseconds(), filter); | |
1245 } | |
1246 | |
1247 bool CleanupProcesses(const FilePath::StringType& executable_name, | 1229 bool CleanupProcesses(const FilePath::StringType& executable_name, |
1248 int64 wait_milliseconds, | 1230 int64 wait_milliseconds, |
1249 int exit_code, | 1231 int exit_code, |
1250 const ProcessFilter* filter) { | 1232 const ProcessFilter* filter) { |
1251 bool exited_cleanly = | 1233 bool exited_cleanly = |
1252 WaitForProcessesToExit( | 1234 WaitForProcessesToExit( |
1253 executable_name, | 1235 executable_name, |
1254 base::TimeDelta::FromMilliseconds(wait_milliseconds), | 1236 base::TimeDelta::FromMilliseconds(wait_milliseconds), |
1255 filter); | 1237 filter); |
1256 if (!exited_cleanly) | 1238 if (!exited_cleanly) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1349 if (IsChildDead(process)) | 1331 if (IsChildDead(process)) |
1350 return; | 1332 return; |
1351 | 1333 |
1352 BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 1334 BackgroundReaper* reaper = new BackgroundReaper(process, 0); |
1353 PlatformThread::CreateNonJoinable(0, reaper); | 1335 PlatformThread::CreateNonJoinable(0, reaper); |
1354 } | 1336 } |
1355 | 1337 |
1356 #endif // !defined(OS_MACOSX) | 1338 #endif // !defined(OS_MACOSX) |
1357 | 1339 |
1358 } // namespace base | 1340 } // namespace base |
OLD | NEW |