From a9bcabee38bedb9b3f2510d4f91b83f6c306b625 Mon Sep 17 00:00:00 2001 From: Eduardo Ramos Testillano Date: Sun, 20 Sep 2015 17:19:00 +0200 Subject: [PATCH] wait for child with WNOHANG|WNOWAIT in order to capture result code for system() function call on thread. --- .../diameter/launcher/testing/TestStep.cpp | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/example/diameter/launcher/testing/TestStep.cpp b/example/diameter/launcher/testing/TestStep.cpp index b1da8fb..bf56391 100644 --- a/example/diameter/launcher/testing/TestStep.cpp +++ b/example/diameter/launcher/testing/TestStep.cpp @@ -9,9 +9,14 @@ // Standard #include #include -#include #include +#include // sigaction, sigemptyset, struct sigaction, SIGCHLD, SA_RESTART, SA_NOCLDSTOP +#include // perror +#include // exit +#include // waitpid, pid_t, WNOHANG + + // Project #include #include @@ -32,18 +37,34 @@ namespace { + + void handle_sigchld(int sig) { + while (waitpid((pid_t)(-1), 0, WNOHANG|WNOWAIT) > 0) {} + } + void cmdRunOnThread (TestStepCmd *step, const std::string &cmd) { + + // Thread running: step->setThreadRunning(true); - int rc = system(cmd.c_str()); - if (rc < 0 && errno == ECHILD) rc = 0; // ignore, it could happens - // I know one reason for this is that SICCHLD is set to SIG_IGN but this - // should not be the case here. SIGCHLD is explicity set to SIG_DFL - // using a sigaction before the call to system(). (Although it is - // normally set to SIG_IGN). There should not be any other threads - // messing about with SIGCHLD. + + // Result code: + int rc = 1; + + struct sigaction sa; + sa.sa_handler = &handle_sigchld; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; + if (sigaction(SIGCHLD, &sa, 0) != -1) { + rc = system(cmd.c_str()); + } + else { + perror(0); + } if (rc < 0) { - step->setErrorMsg(anna::functions::asString("errno = %d", errno)); + char buf[256]; + char const * str = strerror_r(errno, buf, 256); + step->setErrorMsg(anna::functions::asString("errno = %d(%s)", errno, str)); //std::terminate; } else { @@ -53,6 +74,7 @@ namespace { step->setResultCode(rc); step->complete(); // TODO: timeout the system call + // TODO: mutex the step while setting data here !! } } @@ -472,6 +494,7 @@ void TestStepCmd::do_complete() throw() { a_threadRunning = false; if (a_threadDeprecated) { a_threadDeprecated = false; + do_reset(); return; // ignore TODO: interrupt the thread to avoid execution of the script } -- 2.20.1