// 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 {
step->setResultCode(rc);
step->complete();
// TODO: timeout the system call
+ // TODO: mutex the step while setting data here !!
}
}
a_threadRunning = false;
if (a_threadDeprecated) {
a_threadDeprecated = false;
+ do_reset();
return; // ignore TODO: interrupt the thread to avoid execution of the script
}