wait for child with WNOHANG|WNOWAIT in order to capture result code for system()...
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 20 Sep 2015 15:19:00 +0000 (17:19 +0200)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 20 Sep 2015 15:19:00 +0000 (17:19 +0200)
example/diameter/launcher/testing/TestStep.cpp

index b1da8fb..bf56391 100644 (file)
@@ -9,9 +9,14 @@
 // Standard
 #include <string>
 #include <iostream>
-#include <stdio.h>
 #include <errno.h>
 
+#include <signal.h>    // sigaction, sigemptyset, struct sigaction, SIGCHLD, SA_RESTART, SA_NOCLDSTOP
+#include <stdio.h>     // perror
+#include <stdlib.h>    // exit
+#include <sys/wait.h>  // waitpid, pid_t, WNOHANG
+
+
 // Project
 #include <anna/xml/Compiler.hpp>
 #include <anna/core/util/Millisecond.hpp>
 
 
 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
   }