summaryrefslogtreecommitdiffstats
path: root/base/process
diff options
context:
space:
mode:
authorrvargas <rvargas@chromium.org>2015-02-23 16:28:11 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-24 00:29:56 +0000
commit2f70a1515d5f3e6ea3525c079743bfbcb0818b98 (patch)
tree6ac997a1c4ccbd2d62855a25e7eaec27bed5f7f9 /base/process
parent9426fb80a0cc758ed9686c48bb7642d23c229cfa (diff)
downloadchromium_src-2f70a1515d5f3e6ea3525c079743bfbcb0818b98.zip
chromium_src-2f70a1515d5f3e6ea3525c079743bfbcb0818b98.tar.gz
chromium_src-2f70a1515d5f3e6ea3525c079743bfbcb0818b98.tar.bz2
Remove base::WaitForSingleProcess
BUG=417532 Review URL: https://codereview.chromium.org/938453002 Cr-Commit-Position: refs/heads/master@{#317690}
Diffstat (limited to 'base/process')
-rw-r--r--base/process/kill.h6
-rw-r--r--base/process/kill_posix.cc225
-rw-r--r--base/process/kill_win.cc17
-rw-r--r--base/process/process.h2
-rw-r--r--base/process/process_unittest.cc3
-rw-r--r--base/process/process_util_unittest.cc23
6 files changed, 132 insertions, 144 deletions
diff --git a/base/process/kill.h b/base/process/kill.h
index e8ce334..8c0a213 100644
--- a/base/process/kill.h
+++ b/base/process/kill.h
@@ -119,12 +119,6 @@ BASE_EXPORT bool WaitForProcessesToExit(
base::TimeDelta wait,
const ProcessFilter* filter);
-// Wait for a single process to exit. Return true if it exited cleanly within
-// the given time limit. On Linux |handle| must be a child process, however
-// on Mac and Windows it can be any process.
-BASE_EXPORT bool WaitForSingleProcess(ProcessHandle handle,
- base::TimeDelta wait);
-
// Waits a certain amount of time (can be 0) for all the processes with a given
// executable name to exit, then kills off any of them that are still around.
// If filter is non-null, then only processes selected by the filter are waited
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index 5e8b61f..77705ee 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -84,6 +84,97 @@ bool WaitpidWithTimeout(ProcessHandle handle,
return ret_pid > 0;
}
+
+#if defined(OS_MACOSX)
+// Using kqueue on Mac so that we can wait on non-child processes.
+// We can't use kqueues on child processes because we need to reap
+// our own children using wait.
+static bool WaitForSingleNonChildProcess(ProcessHandle handle,
+ TimeDelta wait) {
+ DCHECK_GT(handle, 0);
+ DCHECK(wait.InMilliseconds() == kNoTimeout || wait > TimeDelta());
+
+ ScopedFD kq(kqueue());
+ if (!kq.is_valid()) {
+ DPLOG(ERROR) << "kqueue";
+ return false;
+ }
+
+ struct kevent change = {0};
+ EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
+ int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
+ if (result == -1) {
+ if (errno == ESRCH) {
+ // If the process wasn't found, it must be dead.
+ return true;
+ }
+
+ DPLOG(ERROR) << "kevent (setup " << handle << ")";
+ return false;
+ }
+
+ // Keep track of the elapsed time to be able to restart kevent if it's
+ // interrupted.
+ bool wait_forever = wait.InMilliseconds() == kNoTimeout;
+ TimeDelta remaining_delta;
+ TimeTicks deadline;
+ if (!wait_forever) {
+ remaining_delta = wait;
+ deadline = TimeTicks::Now() + remaining_delta;
+ }
+
+ result = -1;
+ struct kevent event = {0};
+
+ while (wait_forever || remaining_delta > TimeDelta()) {
+ struct timespec remaining_timespec;
+ struct timespec* remaining_timespec_ptr;
+ if (wait_forever) {
+ remaining_timespec_ptr = NULL;
+ } else {
+ remaining_timespec = remaining_delta.ToTimeSpec();
+ remaining_timespec_ptr = &remaining_timespec;
+ }
+
+ result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
+
+ if (result == -1 && errno == EINTR) {
+ if (!wait_forever) {
+ remaining_delta = deadline - TimeTicks::Now();
+ }
+ result = 0;
+ } else {
+ break;
+ }
+ }
+
+ if (result < 0) {
+ DPLOG(ERROR) << "kevent (wait " << handle << ")";
+ return false;
+ } else if (result > 1) {
+ DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
+ << result;
+ return false;
+ } else if (result == 0) {
+ // Timed out.
+ return false;
+ }
+
+ DCHECK_EQ(result, 1);
+
+ if (event.filter != EVFILT_PROC ||
+ (event.fflags & NOTE_EXIT) == 0 ||
+ event.ident != static_cast<uintptr_t>(handle)) {
+ DLOG(ERROR) << "kevent (wait " << handle
+ << "): unexpected event: filter=" << event.filter
+ << ", fflags=" << event.fflags
+ << ", ident=" << event.ident;
+ return false;
+ }
+
+ return true;
+}
+#endif // OS_MACOSX
#endif // !defined(OS_NACL_NONSFI)
TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
@@ -230,7 +321,19 @@ bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
bool WaitForExitCodeWithTimeout(ProcessHandle handle,
int* exit_code,
- base::TimeDelta timeout) {
+ TimeDelta timeout) {
+ ProcessHandle parent_pid = GetParentProcessId(handle);
+ ProcessHandle our_pid = GetCurrentProcessHandle();
+ if (parent_pid != our_pid) {
+#if defined(OS_MACOSX)
+ // On Mac we can wait on non child processes.
+ return WaitForSingleNonChildProcess(handle, timeout);
+#else
+ // Currently on Linux we can't handle non child processes.
+ NOTIMPLEMENTED();
+#endif // OS_MACOSX
+ }
+
int status;
if (!WaitpidWithTimeout(handle, &status, timeout))
return false;
@@ -246,138 +349,28 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle,
}
bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
- base::TimeDelta wait,
+ TimeDelta wait,
const ProcessFilter* filter) {
bool result = false;
// TODO(port): This is inefficient, but works if there are multiple procs.
// TODO(port): use waitpid to avoid leaving zombies around
- base::TimeTicks end_time = base::TimeTicks::Now() + wait;
+ TimeTicks end_time = TimeTicks::Now() + wait;
do {
NamedProcessIterator iter(executable_name, filter);
if (!iter.NextProcessEntry()) {
result = true;
break;
}
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
- } while ((end_time - base::TimeTicks::Now()) > base::TimeDelta());
+ PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
+ } while ((end_time - TimeTicks::Now()) > TimeDelta());
return result;
}
-#if defined(OS_MACOSX)
-// Using kqueue on Mac so that we can wait on non-child processes.
-// We can't use kqueues on child processes because we need to reap
-// our own children using wait.
-static bool WaitForSingleNonChildProcess(ProcessHandle handle,
- base::TimeDelta wait) {
- DCHECK_GT(handle, 0);
- DCHECK(wait.InMilliseconds() == base::kNoTimeout || wait > base::TimeDelta());
-
- ScopedFD kq(kqueue());
- if (!kq.is_valid()) {
- DPLOG(ERROR) << "kqueue";
- return false;
- }
-
- struct kevent change = {0};
- EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
- int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
- if (result == -1) {
- if (errno == ESRCH) {
- // If the process wasn't found, it must be dead.
- return true;
- }
-
- DPLOG(ERROR) << "kevent (setup " << handle << ")";
- return false;
- }
-
- // Keep track of the elapsed time to be able to restart kevent if it's
- // interrupted.
- bool wait_forever = wait.InMilliseconds() == base::kNoTimeout;
- base::TimeDelta remaining_delta;
- base::TimeTicks deadline;
- if (!wait_forever) {
- remaining_delta = wait;
- deadline = base::TimeTicks::Now() + remaining_delta;
- }
-
- result = -1;
- struct kevent event = {0};
-
- while (wait_forever || remaining_delta > base::TimeDelta()) {
- struct timespec remaining_timespec;
- struct timespec* remaining_timespec_ptr;
- if (wait_forever) {
- remaining_timespec_ptr = NULL;
- } else {
- remaining_timespec = remaining_delta.ToTimeSpec();
- remaining_timespec_ptr = &remaining_timespec;
- }
-
- result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
-
- if (result == -1 && errno == EINTR) {
- if (!wait_forever) {
- remaining_delta = deadline - base::TimeTicks::Now();
- }
- result = 0;
- } else {
- break;
- }
- }
-
- if (result < 0) {
- DPLOG(ERROR) << "kevent (wait " << handle << ")";
- return false;
- } else if (result > 1) {
- DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
- << result;
- return false;
- } else if (result == 0) {
- // Timed out.
- return false;
- }
-
- DCHECK_EQ(result, 1);
-
- if (event.filter != EVFILT_PROC ||
- (event.fflags & NOTE_EXIT) == 0 ||
- event.ident != static_cast<uintptr_t>(handle)) {
- DLOG(ERROR) << "kevent (wait " << handle
- << "): unexpected event: filter=" << event.filter
- << ", fflags=" << event.fflags
- << ", ident=" << event.ident;
- return false;
- }
-
- return true;
-}
-#endif // OS_MACOSX
-
-bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) {
- ProcessHandle parent_pid = GetParentProcessId(handle);
- ProcessHandle our_pid = GetCurrentProcessHandle();
- if (parent_pid != our_pid) {
-#if defined(OS_MACOSX)
- // On Mac we can wait on non child processes.
- return WaitForSingleNonChildProcess(handle, wait);
-#else
- // Currently on Linux we can't handle non child processes.
- NOTIMPLEMENTED();
-#endif // OS_MACOSX
- }
-
- int status;
- if (!WaitpidWithTimeout(handle, &status, wait))
- return false;
- return WIFEXITED(status);
-}
-
bool CleanupProcesses(const FilePath::StringType& executable_name,
- base::TimeDelta wait,
+ TimeDelta wait,
int exit_code,
const ProcessFilter* filter) {
bool exited_cleanly = WaitForProcessesToExit(executable_name, wait, filter);
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index f280c6f..7daf5f8 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -189,7 +189,7 @@ bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
bool WaitForExitCodeWithTimeout(ProcessHandle handle,
int* exit_code,
- base::TimeDelta timeout) {
+ TimeDelta timeout) {
if (::WaitForSingleObject(
handle, static_cast<DWORD>(timeout.InMilliseconds())) != WAIT_OBJECT_0)
return false;
@@ -202,7 +202,7 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle,
}
bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
- base::TimeDelta wait,
+ TimeDelta wait,
const ProcessFilter* filter) {
bool result = true;
DWORD start_time = GetTickCount();
@@ -224,13 +224,8 @@ bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
return result;
}
-bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) {
- int exit_code;
- return WaitForExitCodeWithTimeout(handle, &exit_code, wait) && exit_code == 0;
-}
-
bool CleanupProcesses(const FilePath::StringType& executable_name,
- base::TimeDelta wait,
+ TimeDelta wait,
int exit_code,
const ProcessFilter* filter) {
if (WaitForProcessesToExit(executable_name, wait, filter))
@@ -249,9 +244,9 @@ void EnsureProcessTerminated(Process process) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
- base::Bind(&TimerExpiredTask::TimedOut,
- base::Owned(new TimerExpiredTask(process.Pass()))),
- base::TimeDelta::FromMilliseconds(kWaitInterval));
+ Bind(&TimerExpiredTask::TimedOut,
+ Owned(new TimerExpiredTask(process.Pass()))),
+ TimeDelta::FromMilliseconds(kWaitInterval));
}
} // namespace base
diff --git a/base/process/process.h b/base/process/process.h
index 77d2bce..a834a29 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -98,6 +98,8 @@ class BASE_EXPORT Process {
// Waits for the process to exit. Returns true on success.
// On POSIX, if the process has been signaled then |exit_code| is set to -1.
+ // On Linux this must be a child process, however on Mac and Windows it can be
+ // any process.
bool WaitForExit(int* exit_code);
// Same as WaitForExit() but only waits for up to |timeout|.
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
index 4ea7a5e..535a36f 100644
--- a/base/process/process_unittest.cc
+++ b/base/process/process_unittest.cc
@@ -124,7 +124,8 @@ TEST_F(ProcessTest, Terminate) {
exit_code = kDummyExitCode;
int kExpectedExitCode = 250;
process.Terminate(kExpectedExitCode);
- WaitForSingleProcess(process.Handle(), TestTimeouts::action_max_timeout());
+ process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
+ &exit_code);
EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
GetTerminationStatus(process.Handle(), &exit_code));
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index 5ed15d2..11d8874 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -151,8 +151,9 @@ MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
TEST_F(ProcessUtilTest, SpawnChild) {
base::Process process = SpawnChild("SimpleChildProcess");
ASSERT_TRUE(process.IsValid());
- EXPECT_TRUE(base::WaitForSingleProcess(process.Handle(),
- TestTimeouts::action_max_timeout()));
+ int exit_code;
+ EXPECT_TRUE(process.WaitForExitWithTimeout(
+ TestTimeouts::action_max_timeout(), &exit_code));
}
MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
@@ -167,8 +168,9 @@ TEST_F(ProcessUtilTest, KillSlowChild) {
base::Process process = SpawnChild("SlowChildProcess");
ASSERT_TRUE(process.IsValid());
SignalChildren(signal_file.c_str());
- EXPECT_TRUE(base::WaitForSingleProcess(process.Handle(),
- TestTimeouts::action_max_timeout()));
+ int exit_code;
+ EXPECT_TRUE(process.WaitForExitWithTimeout(
+ TestTimeouts::action_max_timeout(), &exit_code));
remove(signal_file.c_str());
}
@@ -550,12 +552,12 @@ int ProcessUtilTest::CountOpenFDsInChild() {
#if defined(THREAD_SANITIZER)
// Compiler-based ThreadSanitizer makes this test slow.
- CHECK(base::WaitForSingleProcess(process.Handle(),
- base::TimeDelta::FromSeconds(3)));
+ base::TimeDelta timeout = base::TimeDelta::FromSeconds(3);
#else
- CHECK(base::WaitForSingleProcess(process.Handle(),
- base::TimeDelta::FromSeconds(1)));
+ base::TimeDelta timeout = base::TimeDelta::FromSeconds(1);
#endif
+ int exit_code;
+ CHECK(process.WaitForExitWithTimeout(timeout, &exit_code));
ret = IGNORE_EINTR(close(fds[0]));
DPCHECK(ret == 0);
@@ -891,8 +893,9 @@ TEST_F(ProcessUtilTest, DelayedTermination) {
base::Process child_process = SpawnChild("process_util_test_never_die");
ASSERT_TRUE(child_process.IsValid());
base::EnsureProcessTerminated(child_process.Duplicate());
- base::WaitForSingleProcess(child_process.Handle(),
- base::TimeDelta::FromSeconds(5));
+ int exit_code;
+ child_process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(5),
+ &exit_code);
// Check that process was really killed.
EXPECT_TRUE(IsProcessDead(child_process.Handle()));