bool process::kill(){ int r = ::kill(pid_, SIGTERM); if(r!=0){ perror("cannot kill"); return false; } int status = 0; waitpid(pid_, &status,0); if(WCOREDUMP(status)){ LOG(ERROR) << name_ << " coredumped."; }//TODO: add more error processing DLOG(INFO) << "stopped: " << pid_; DLOG(ERROR) << "stopped: " << pid_; return true; }
static void log_status (int status) { if (WIFEXITED (status)) { if (0 == WEXITSTATUS (status)) syslog (LOG_INFO, "Info: collectd terminated with exit status %i", WEXITSTATUS (status)); else syslog (LOG_WARNING, "Warning: collectd terminated with exit status %i", WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) { syslog (LOG_WARNING, "Warning: collectd was terminated by signal %i%s", WTERMSIG (status), WCOREDUMP (status) ? " (core dumped)" : ""); } return; } /* log_status */
static void child_exited(int sig) { struct rusage ru; int status, result; result = wait3(&status, 0, &ru); printf("wait3() status: %d; return %d: %s\n", status, result, strerror(errno)); if (WIFEXITED(status)) { printf("Child with pid %d exited normally\n", result); } if (WIFSIGNALED(status)) { printf("Child caught signal %d\n", WTERMSIG(status)); printf("Child did%s produce a core dump\n", WCOREDUMP(status) ? "" : " not"); } exit(1); }
void prexit(stat) { if (WIFEXITED(stat)) printf("normal termination, exit status = %d\n", WEXITSTATUS(stat)); else if (WIFSIGNALED(stat)) printf("abnormal termination, signal = %d %s\n", WTERMSIG(stat), #ifdef WCOREDUMP WCOREDUMP(stat) ? "( core file generated )" : "" #else "" #endif ); else if (WIFSTOPPED(stat)) printf("child stopped, signal = %d\n", WSTOPSIG(stat)); else if (WIFCONTINUED(stat)) printf("child stopped, signal = %d\n", WSTOPSIG(stat)); }
static Waitmsg* _wait(int pid4, int opt) { int pid, status, cd; struct rusage ru; char tmp[64]; ulong u, s; Waitmsg *w; w = malloc(sizeof *w + 200); if(w == nil) return nil; memset(w, 0, sizeof *w); w->msg = (char*)&w[1]; for(;;){ /* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */ if(pid4 == -1) pid = wait3(&status, opt, &ru); else pid = wait4(pid4, &status, opt, &ru); if(pid <= 0) { free(w); return nil; } u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000); s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000); w->pid = pid; w->time[0] = u; w->time[1] = s; w->time[2] = u+s; if(WIFEXITED(status)){ if(status) sprint(w->msg, "%d", status); return w; } if(WIFSIGNALED(status)){ cd = WCOREDUMP(status); sprint(w->msg, "signal: %s", _p9sigstr(WTERMSIG(status), tmp)); if(cd) strcat(w->msg, " (core dumped)"); return w; } } }
static void log_coredump(struct service *service, string_t *str, int status) { #ifdef WCOREDUMP int signum = WTERMSIG(status); if (WCOREDUMP(status)) { str_append(str, " (core dumped)"); return; } if (signum != SIGABRT && signum != SIGSEGV && signum != SIGBUS) return; /* let's try to figure out why we didn't get a core dump */ if (core_dumps_disabled) { str_printfa(str, " (core dumps disabled)"); return; } #ifndef HAVE_PR_SET_DUMPABLE if (!service->set->drop_priv_before_exec && service->uid != 0) { str_printfa(str, " (core not dumped - set service %s " "{ drop_priv_before_exec=yes })", service->set->name); return; } if (*service->set->privileged_group != '\0' && service->uid != 0) { str_printfa(str, " (core not dumped - service %s " "{ privileged_group } prevented it)", service->set->name); return; } #else if (!service->set->login_dump_core && service->type == SERVICE_TYPE_LOGIN) { str_printfa(str, " (core not dumped - add -D parameter to " "service %s { executable }", service->set->name); return; } #endif str_append(str, " (core not dumped)"); #endif }
void pr_exit(int status) { if (WIFEXITED(status)) { printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status), #ifdef WCOREDUMP WCOREDUMP(status) ? " (core file generated)" : "" #else "" #endif ); } else if (WIFSTOPPED(status)) { printf("child stopped, signal number = %d\n", WSTOPSIG(status)); } }
/// Writes a generic result file for an ATF broken result. /// /// \param reason Textual explanation of the result. /// \param status Exit code of the test program as returned by wait(). /// \param output Path to the generic result file to create. /// \param [out] success Whether the result should be considered a success or /// not; e.g. passed and skipped are successful, but failed is not. /// /// \return An error if the conversion fails; OK otherwise. static kyua_error_t convert_broken(const char* reason, int status, const char* output, bool* success) { if (WIFEXITED(status)) { *success = false; return kyua_result_write( output, KYUA_RESULT_BROKEN, "%s; test case exited with code %d", reason, WEXITSTATUS(status)); } else { assert(WIFSIGNALED(status)); *success = false; return kyua_result_write( output, KYUA_RESULT_BROKEN, "%s; test case received signal %d%s", reason, WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); } }
strbuf strbuf_append_exit_status(strbuf sb, int status) { if (WIFEXITED(status)) strbuf_sprintf(sb, "exited normally with status %u", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) { strbuf_sprintf(sb, "terminated by signal %u (%s)", WTERMSIG(status), strsignal(WTERMSIG(status))); #ifdef WCOREDUMP if (WCOREDUMP(status)) strbuf_puts(sb, " and dumped core"); #endif } else if (WIFSTOPPED(status)) strbuf_sprintf(sb, "stopped by signal %u (%s)", WSTOPSIG(status), strsignal(WSTOPSIG(status))); #ifdef WIFCONTINUED else if (WIFCONTINUED(status)) strbuf_sprintf(sb, "continued by signal %u (SIGCONT)", SIGCONT); #endif return sb; }
static void print_wait_status (int status) { if (WIFEXITED (status)) printf ("child exited, status:%d\n", WEXITSTATUS (status)); else if (WIFSIGNALED (status)) { printf ("child killed by signal %s", strsignal (WTERMSIG (status))); if (WCOREDUMP (status)) printf (" (core dumped)"); printf ("\n"); } else if (WIFSTOPPED (status)) printf ("child stopped by signal %s\n", strsignal (WSTOPSIG (status))); else if (WIFCONTINUED (status)) printf ("child continued\n"); else printf ("what happened to this child? (status:0x%08x)\n", (unsigned)status); }
static int subproc_check(int status, const char *desc, enum subproc_flags flags) { void (*out)(const char *fmt, ...) DPKG_ATTR_PRINTF(1); int n; if (flags & SUBPROC_WARN) out = warning; else out = ohshit; if (WIFEXITED(status)) { n = WEXITSTATUS(status); if (!n) return 0; if (flags & SUBPROC_RETERROR) return n; out(_("subprocess %s returned error exit status %d"), desc, n); } else if (WIFSIGNALED(status)) { n = WTERMSIG(status); if (!n) return 0; if ((flags & SUBPROC_NOPIPE) && n == SIGPIPE) return 0; if (flags & SUBPROC_RETSIGNO) return n; if (n == SIGINT) out(_("subprocess %s was interrupted"), desc); else out(_("subprocess %s was killed by signal (%s)%s"), desc, strsignal(n), WCOREDUMP(status) ? _(", core dumped") : ""); } else { if (flags & SUBPROC_RETERROR) return -1; out(_("subprocess %s failed with wait status code %d"), desc, status); } return -1; }
// // Various signal/error handling functions that can't be put into the class // void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging) { exited = false; process_status = -1; // The child process exited. Call its callback, and then clean it up if (WIFEXITED(waitpid_status)) { process_status = WEXITSTATUS(waitpid_status); exited = true; if (do_logging) { llinfos << "get_child_status - Child exited cleanly with return of " << process_status << llendl; } return; } else if (WIFSIGNALED(waitpid_status)) { process_status = WTERMSIG(waitpid_status); exited = true; if (do_logging) { llinfos << "get_child_status - Child died because of uncaught signal " << process_status << llendl; #ifdef WCOREDUMP if (WCOREDUMP(waitpid_status)) { llinfos << "get_child_status - Child dumped core" << llendl; } else { llinfos << "get_child_status - Child didn't dump core" << llendl; } #endif } return; } else if (do_logging) { // This is weird. I just dump the waitpid status into the status code, // not that there's any way of telling what it is... llinfos << "get_child_status - Got SIGCHILD but child didn't exit" << llendl; process_status = waitpid_status; } }
static gboolean child_waitpid(mainloop_child_t *child, int flags) { int rc = 0; int core = 0; int signo = 0; int status = 0; int exitcode = 0; rc = waitpid(child->pid, &status, flags); if(rc == 0) { crm_perror(LOG_DEBUG, "wait(%d) = %d", child->pid, rc); return FALSE; } else if(rc != child->pid) { signo = SIGCHLD; exitcode = 1; status = 1; crm_perror(LOG_ERR, "Call to waitpid(%d) failed", child->pid); } else { crm_trace("Managed process %d exited: %p", child->pid, child); if (WIFEXITED(status)) { exitcode = WEXITSTATUS(status); crm_trace("Managed process %d (%s) exited with rc=%d", child->pid, child->desc, exitcode); } else if (WIFSIGNALED(status)) { signo = WTERMSIG(status); crm_trace("Managed process %d (%s) exited with signal=%d", child->pid, child->desc, signo); } #ifdef WCOREDUMP if (WCOREDUMP(status)) { core = 1; crm_err("Managed process %d (%s) dumped core", child->pid, child->desc); } #endif } if (child->callback) { child->callback(child, child->pid, core, signo, exitcode); } return TRUE; }
void affichage_type_de_terminaison (pid_t pid, int status) { fprintf(stdout, "Le processus %ld ", (long)pid); if (WIFEXITED(status)) { fprintf (stdout, "s'est termine normalement avec le code %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { fprintf (stdout, "s'est termine a cause du signal %d (%s)\n", WTERMSIG(status), sys_siglist[WTERMSIG(status)]); if (WCOREDUMP(status)) { fprintf(stdout, "Fichier image core cree\n"); } } else if (WIFSTOPPED(status)) { fprintf(stdout, "s'est arrete a cause du signal %d (%s)\n", WSTOPSIG(status), sys_siglist[WSTOPSIG(status)]); } }
int main(int argc, char *argv[]) { pid_t pid; int status, retval, whatToDo = 0; char str[8]; if (argc > 1) whatToDo = atoi(argv[1]); // get job number for child pid = fork(); // fork child switch (pid) { case -1: perror("Could not fork"); break; case 0: sprintf(str, "%d",whatToDo); retval = execl("./ChildProgA8.e", "ChildProgA8.e", str, NULL); if (retval < 0) perror("\nexecl not successful"); break; default: if (whatToDo <= 3) { if (whatToDo == 3) { sleep(1); kill(pid, SIGABRT); // send signal SIGABTR to child } wait(&status); if (WIFEXITED(status)) printf("Child exits with status %d\n", WEXITSTATUS(status)); if (WIFSIGNALED(status)) { printf("Child exits on signal %d\n", WTERMSIG(status)); printf("Child exits with core dump %d\n", WCOREDUMP(status)); } } else { usleep(500*1000); while (!waitpid(pid, &status, WNOHANG)) { printf(". . . child is playing\n"); usleep(500*1000); } printf("Child has exited with 'exit(%d)'\n", WEXITSTATUS(status)); } break; } exit(0); }
static int Reap_Child(char *prog, int * pid, int * status) { int ret; ret = wait(status); if (ret >= 0) { *pid = ret; if (WCOREDUMP(*status)) Log("\"%s\" core dumped!\n", prog); if ((WIFSIGNALED(*status) != 0) || ((WEXITSTATUS(*status) != 0) && (WEXITSTATUS(*status) != SALSRV_EXIT_VOLGROUP_LINK))) Log("\"%s\" (pid=%d) terminated abnormally!\n", prog, ret); } else { Log("wait returned -1\n"); } return ret; }
static int cmd_lstopo (optparse_t *p, int ac, char *av[]) { int status; struct hwloc_topo *t = hwloc_topo_create (p); assert (t != NULL); status = exec_lstopo (p, ac, av, hwloc_topo_topology (t)); if (status) { if (WIFEXITED (status) && WEXITSTATUS (status) != ENOENT) log_msg_exit ("lstopo: Exited with %d", WEXITSTATUS (status)); if (WIFSIGNALED (status) && WTERMSIG (status) != SIGPIPE) log_msg_exit ("lstopo: %s%s", strsignal (WTERMSIG (status)), WCOREDUMP (status) ? " (core dumped)" : ""); } hwloc_topo_destroy (t); return (0); }
int dmngr_wait_chld_f (void) { int chld_status; pid_t chld_pid = waitpid (-1, &chld_status, WNOHANG); /* Error or no child exists */ if (chld_pid == (pid_t) -1) { /* Not actually an error if ECHILD. Do nothing... */ if (errno == ECHILD) { /* DBE_DEBUG (DBG_DEV_MNGR | DBG_LVL_INFO, "[dev_mngr] no child to wait for\n"); */ return 0; } return -1; } /* Child exists but have not changed its state */ if (chld_pid == (pid_t) 0) { /* DBE_DEBUG (DBG_DEV_MNGR | DBG_LVL_INFO, "[dev_mngr] Child has not changed its state\n"); */ return 0; } /* Child exists and has changed its state. Check fior the return status */ if (WIFEXITED (chld_status)) { DBE_DEBUG (DBG_DEV_MNGR | DBG_LVL_WARN, "[dev_mngr] Child exited%s with status %d\n", WCOREDUMP(chld_status) ? " and dumped core" : "", WEXITSTATUS(chld_status)); __dev_nums--; } if (WIFSTOPPED (chld_status)) { DBE_DEBUG (DBG_DEV_MNGR | DBG_LVL_WARN, "[dev_mngr] Child stopped by signal %d\n", WSTOPSIG(chld_status)); } if (WIFSIGNALED (chld_status)) { DBE_DEBUG (DBG_DEV_MNGR | DBG_LVL_WARN, "[dev_mngr] Child signalled by signal %d\n", WTERMSIG(chld_status)); __dev_nums--; } return 0; }
static inline int sendChildrenOutputsToSyslog(const pid_t child, int stdoutReadPipe, int stderrReadPipe, int eventsReadPipe, int stdOutLogLevel, int stdErrLogLevel) { int error = EXIT_SUCCESS; outputToSyslogParam stdoutParams, stderrParams; pthread_t stdoutThread, stderrThread; stdoutParams.pid = child; stdoutParams.pipe = stdoutReadPipe; stdoutParams.level = stdOutLogLevel; stderrParams.pid = child; stderrParams.pipe = stderrReadPipe; stderrParams.level = stdErrLogLevel; error = pthread_create(&stdoutThread, NULL, sendChildOutputToSyslogThread, &stdoutParams); if (0 == error) { error = pthread_create(&stderrThread, NULL, sendChildOutputToSyslogThread, &stderrParams); if (0 == error) { int childStatus = -1; const pid_t pid = waitpid(child, &childStatus, 0); if (pid != -1) { void *pthreadReturn = NULL; DEBUG_MSG("child ended"); if (WIFEXITED(childStatus)) { const int exitStatus = WEXITSTATUS(childStatus); INFO_MSG("process %d ended with status %d", child, exitStatus); } else if WIFSIGNALED(childStatus) { const int signalNumber = WTERMSIG(childStatus); if (WCOREDUMP(childStatus)) { NOTICE_MSG("child process %d terminated by signal %d (core dumped)", child, signalNumber); } else { NOTICE_MSG("child process %d terminated by signal %d", child, signalNumber); } } error = pthread_join(stdoutThread, &pthreadReturn); if (error != 0) { ERROR_MSG("pthread_join stdoutThread error %d (%m)", error); } error = pthread_join(stderrThread, &pthreadReturn); if (error != 0) { ERROR_MSG("pthread_join stderrThread error %d (%m)", error); } } else {
/* * Collect the exit status of the child process */ static int ni_process_reap(ni_process_t *pi) { int rv; if (pi->pid == 0) { ni_error("%s: child already reaped", __func__); return 0; } rv = waitpid(pi->pid, &pi->status, WNOHANG); if (rv == 0) { /* This is an ugly workaround. Sometimes, we seem to get a hangup on the socket even * though the script (provably) still has its end of the socket pair open for writing. */ ni_error("%s: process %u has not exited yet; now doing a blocking waitpid()", __func__, pi->pid); rv = waitpid(pi->pid, &pi->status, 0); } if (rv < 0) { ni_error("%s: waitpid returns error (%m)", __func__); return -1; } if (WIFEXITED(pi->status)) ni_debug_extension("subprocess %d (%s) exited with status %d", pi->pid, pi->process->command, WEXITSTATUS(pi->status)); else if (WIFSIGNALED(pi->status)) ni_debug_extension("subprocess %d (%s) died with signal %d%s", pi->pid, pi->process->command, WTERMSIG(pi->status), WCOREDUMP(pi->status)? " (core dumped)" : ""); else ni_debug_extension("subprocess %d (%s) transcended into nirvana", pi->pid, pi->process->command); pi->pid = 0; if (pi->notify_callback) pi->notify_callback(pi); return 0; }
void eprint_status (const char* command, int status) { if (status == 0) return; eprintf ("%s: status 0x%04X", command, status); if (WIFEXITED (status)) { eprintf (", exit %d", WEXITSTATUS (status)); } if (WIFSIGNALED (status)) { eprint_signal ("Terminated", WTERMSIG (status)); #ifdef WCOREDUMP if (WCOREDUMP (status)) eprintf (", core dumped"); #endif } if (WIFSTOPPED (status)) { eprint_signal ("Stopped", WSTOPSIG (status)); } if (WIFCONTINUED (status)) { eprintf (", Continued"); } eprintf ("\n"); }
static void print_exit_status(pid_t pid, int wstat) { (void) printf("%d: ", (int)pid); if (WIFSIGNALED(wstat)) { char buf[SIG2STR_MAX]; int sig = WTERMSIG(wstat); if (sig2str(sig, buf) == 0) (void) printf("killed by signal %s", buf); else (void) printf("killed by signal %d", sig); if (WCOREDUMP(wstat)) (void) printf(" (core dumped)"); } else { (void) printf("exited with status %d", WEXITSTATUS(wstat)); } (void) printf("\n"); }
inline void report_external_failure(const char *prog, int status) { if (status == 0) { // success } if (status == -1) { fprintf(stderr, "Program %s was not run due to a system error\n", prog); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 127) { // shell error, maybe the program couldn't be found? // the shell already prints out a message when this happens } else { fprintf(stderr, "Program %s exited with value %d\n", prog, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { fprintf(stderr, "Program %s died from signal %d, %s coredump\n", prog, WTERMSIG(status), (WCOREDUMP(status) ? "with" : "without")); } else { fprintf(stderr, "Unknown error running %s, system returned status %d\n", prog, status); } }
static void crmdManagedChildDied(GPid pid, gint status, gpointer user_data) { struct crm_subsystem_s *the_subsystem = user_data; if(WIFSIGNALED(status)) { int signo = WTERMSIG(status); int core = WCOREDUMP(status); crm_notice("Child process %s terminated with signal %d (pid=%d, core=%d)", the_subsystem->name, signo, the_subsystem->pid, core); } else if(WIFEXITED(status)) { int exitcode = WEXITSTATUS(status); do_crm_log(exitcode == 0 ? LOG_INFO : LOG_ERR, "Child process %s exited (pid=%d, rc=%d)", the_subsystem->name, the_subsystem->pid, exitcode); } else { crm_err("Process %s:[%d] exited?", the_subsystem->name, the_subsystem->pid); } }
static const char * decode_wait_status(int status) { static char c[128]; char b[32]; int first; c[0] = '\0'; first = 1; if (WIFCONTINUED(status)) { first = 0; strlcat(c, "CONT", sizeof(c)); } if (WIFEXITED(status)) { if (first) first = 0; else strlcat(c, ",", sizeof(c)); snprintf(b, sizeof(b), "EXIT(%d)", WEXITSTATUS(status)); strlcat(c, b, sizeof(c)); } if (WIFSIGNALED(status)) { if (first) first = 0; else strlcat(c, ",", sizeof(c)); snprintf(b, sizeof(b), "SIG(%s)", strsignal(WTERMSIG(status))); strlcat(c, b, sizeof(c)); if (WCOREDUMP(status)) strlcat(c, ",CORE", sizeof(c)); } if (WIFSTOPPED(status)) { if (first) first = 0; else strlcat(c, ",", sizeof(c)); snprintf(b, sizeof(b), "SIG(%s)", strsignal(WSTOPSIG(status))); strlcat(c, b, sizeof(c)); } return (c); }
static void forkzio_wait (pid_t pid) { int s; if (waitpid (pid, &s, 0) < 0) err_exit ("waitpid"); if (WIFEXITED (s)) { int rc = WEXITSTATUS (s); if (rc == 0) msg ("Child exited normally."); else msg ("Child exited with %d", rc); } else if (WIFSIGNALED (s)) { msg ("Child exited on signal %d%s", WTERMSIG (s), WCOREDUMP (s) ? " (core dumped)" : ""); } else if (WIFSTOPPED (s)) { msg ("Stopped."); } else if (WIFCONTINUED (s)) { msg ("Continued."); } }
void sig_display(int status) { int i; i = 0; if (WIFSIGNALED(status)) { while (g_sig_mess[i].mess != NULL) { if (g_sig_mess[i].sig == WTERMSIG(status)) { fprintf(stderr, "%s", g_sig_mess[i].mess); if (WCOREDUMP(status)) fprintf(stderr, " (core dumped)"); fprintf(stderr, "\n"); return ; } i++; } } }
void process_handle_child_termination(int signal) { pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG))) { if (pid == -1) { if (errno == EINTR) continue; else break; } number_of_children--; remove_process_info(pid); if (WIFEXITED(status)) { DPRINTF(E_DEBUG, L_GENERAL, "Process %d exited normally with exit status %d\n", (int)pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { #ifdef WCOREDUMP DPRINTF(E_ERROR, L_GENERAL, "Process %d terminated by signal %d. A core dump was%sproduced.\n", (int)pid, WTERMSIG(status), WCOREDUMP(status) ? " " : " not "); #else DPRINTF(E_ERROR, L_GENERAL, "Process %d terminated by signal %d\n", (int)pid, WTERMSIG(status)); #endif } } }
pid_t AmuleWaitPid(pid_t pid, int *status, int options, wxString *msg) { *status = 0; pid_t result = waitpid(pid, status, options); if (result == -1) { *msg << CFormat(wxT("Error: waitpid() call failed: %m.")); } else if (result == 0) { if (options & WNOHANG) { *msg << wxT("The child is alive."); } else { *msg << wxT("Error: waitpid() call returned 0 but " "WNOHANG was not specified in options."); } } else { if (WIFEXITED(*status)) { *msg << wxT("Child has terminated with status code `") << WEXITSTATUS(*status) << wxT("'."); } else if (WIFSIGNALED(*status)) { *msg << wxT("Child was killed by signal `") << WTERMSIG(*status) << wxT("'."); if (WCOREDUMP(*status)) { *msg << wxT(" A core file has been dumped."); } } else if (WIFSTOPPED(*status)) { *msg << wxT("Child has been stopped by signal `") << WSTOPSIG(*status) << wxT("'."); #ifdef WIFCONTINUED /* Only found in recent kernels. */ } else if (WIFCONTINUED(*status)) { *msg << wxT("Child has received `SIGCONT' and has continued execution."); #endif } else { *msg << wxT("The program was not able to determine why the child has signaled."); } } return result; }
/// Forks and executes the cleanup of a test case in a controlled manner. /// /// \param test_program Path to the test program to execute. /// \param test_case Name of the test case to run. /// \param result_file Path to the ATF result file created by the body of the /// test case. The cleanup may update such file if it fails. /// \param user_variables Set of configuration variables to pass to the test. /// \param run_params Settings to control the subprocess. /// \param body_success The success value returned by run_body(). /// \param [out] success Set to true if the test case runs properly and returns /// a result that is to be considered as successful. /// /// \return OK if all goes well, an error otherwise. Note that a failed test /// case cleanup is denoted by setting success to false on exit, not by /// returning an error. static kyua_error_t run_cleanup(const char* test_program, const char* test_case, const char* result_file, const char* const user_variables[], const kyua_run_params_t* run_params, const bool body_success, bool* success) { kyua_error_t error; pid_t pid; error = kyua_run_fork(run_params, &pid); if (!kyua_error_is_set(error) && pid == 0) { exec_cleanup(test_program, test_case, user_variables); } assert(pid != -1 && pid != 0); if (kyua_error_is_set(error)) goto out; int status; bool timed_out; error = kyua_run_wait(pid, &status, &timed_out); if (kyua_error_is_set(error)) goto out; if (WIFSIGNALED(status) && WCOREDUMP(status)) { kyua_stacktrace_dump(test_program, pid, run_params, stderr); } if (body_success) { // If the body has reported a successful result, we inspect the status // of the cleanup routine. If the cleanup has failed, then we need to // mark the test as broken. However, if the body itself had failed, we // don't do this to give preference to the original result, which is // probably more informative. error = kyua_atf_result_cleanup_rewrite(result_file, status, timed_out, success); } out: return error; }