[PATCH xorg-gtest 4/8] process: wait for SIGCHLD instead of busy looping
Peter Hutterer
peter.hutterer at who-t.net
Tue Oct 9 22:14:29 PDT 2012
If for some reason we fail to handle the signals, usleep for the timeout
instead. This will slow down the tests, but still behave properly. And if a
test fails with the usleep, the SCOPED_TRACE will print out the warnings.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/process.cpp | 47 +++++++++++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 16 deletions(-)
diff --git a/src/process.cpp b/src/process.cpp
index 0b0ddc3..7f7d330 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -127,25 +127,40 @@ void xorg::testing::Process::Start(const std::string& program, ...) {
}
bool xorg::testing::Process::WaitForExit(unsigned int timeout) {
- for (unsigned int i = 0; i < timeout * 100; i++) {
- int status;
- int pid = waitpid(Pid(), &status, WNOHANG);
-
- if (pid == Pid()) {
- if (WIFEXITED(status)) {
- d_->state = WEXITSTATUS(status) ? FINISHED_FAILURE : FINISHED_SUCCESS;
- return true;
- } else if (WIFSIGNALED(status)) {
- d_->state = FINISHED_FAILURE;
- return true;
- }
- } else if (pid == -1)
- return errno == ECHILD;
+ sigset_t sig_mask, old_mask;
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGCHLD);
+
+ if (sigprocmask(SIG_BLOCK, &sig_mask, &old_mask) == 0) {
+ struct timespec sig_timeout = {timeout / 1000,
+ (timeout % 1000) * 1000000L};
+
+ if (sigtimedwait(&sig_mask, NULL, &sig_timeout) != SIGCHLD && errno != EAGAIN) {
+ SCOPED_TRACE("INFO: Failure waiting for SIGCHLD: " +
+ std::string(strerror(errno)) + ". I slept instead.");
+ usleep(timeout * 1000);
+ }
- usleep(10);
+ if (!sigismember(&sig_mask, SIGCHLD)) {
+ if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) == -1)
+ SCOPED_TRACE("WARNING: Failed to unblock SIGCHLD. Tests may behave funny.\n");
+ }
+ } else { /* oops, can't wait for SIGCHLD, sleep instead */
+ SCOPED_TRACE("INFO: Failed to set SIGCHLD mask, sleeping instead.\n");
+ usleep(timeout * 1000);
}
- return false;
+ int status;
+ int pid = waitpid(Pid(), &status, WNOHANG);
+ if (pid == Pid()) {
+ if (WIFEXITED(status)) {
+ d_->state = WEXITSTATUS(status) ? FINISHED_FAILURE : FINISHED_SUCCESS;
+ } else if (WIFSIGNALED(status)) {
+ d_->state = FINISHED_FAILURE;
+ }
+ return true;
+ } else
+ return (pid == -1 && errno == ECHILD);
}
bool xorg::testing::Process::KillSelf(int signal, unsigned int timeout) {
--
1.7.11.4
More information about the xorg-devel
mailing list