1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/* Spawn a process and wait a certain amount of time for it to finish.
Input: 1st arg is the number of seconds to wait.
2nd arg is the path to the executable.
3rd-nth args are the arguments to the executable.
Return values: */
enum { OK, FAILED, TIMEOUT, GOTSIGNAL, NOFORK, NOEXEC };
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define TIMEARG 1
#define PGMARG 2
char const* signames[NSIG]={NULL} ;
const char *getsigname(int sig) {
static char buffer[30];
#define ONESIG(SIGX) if (sig==SIGX) return #SIGX ;
#include <initsigs.i>
#undef ONESIG
sprintf(buffer,"unknown signal %d",sig);
return buffer ;
}
static volatile signal_handled = 0;
/* The signal handler */
static void handler()
{
/* Simply return (this should wake up the waiting process?) */
signal_handled = 1;
return;
}
int main(int argc, char** argv)
{
/* Get the time from the arguments (divided by TIMESTEP) */
int time = atoi(argv[TIMEARG]) ;
pid_t child = vfork();
if (child == -1) {
/* Fork was not possible. */
return NOFORK;
}
else if (child == 0) {
/* This is the child process */
/* Redirect stderr to stdout */
/* (tcl assumes any output to stderr means failure) */
dup2(1,2);
/* Run the command. */
if (execvp(argv[PGMARG],argv+PGMARG) == -1) {
printf("Could not execute '%s ...': %s\n", argv[PGMARG],
strerror(errno));
return 1 ;
}
}
else {
/* This is the parent process. Wait for the child to terminate or
timeout. */
int childstatus ;
pid_t waitstatus ;
/* Setup handler for child termination. */
static struct sigaction act ;
act.sa_handler = handler ;
sigemptyset(&act.sa_mask);
act.sa_flags = 0 ;
sigaction(SIGALRM,&act,NULL);
alarm(time);
/* wait for the child to terminate or the alarm to sound
* (whichever comes first)
*/
waitstatus = wait(&childstatus);
if ( waitstatus != child ) {
/* We timed out. */
/* Kill the child. */
kill(child, SIGKILL);
if ( signal_handled )
printf("\n@UNRESOLVED@\n%s: timed out after %d seconds\n",
argv[PGMARG],time);
else
printf("\n@UNRESOLVED@\n%s: wait() failed\n",argv[0]);
return TIMEOUT;
}
if ( waitstatus != child ) {
printf("@@!!@@\nwait returned %d, but the child is %d\n",
(int)waitstatus,(int)child);
}
if ( WIFEXITED(childstatus) ) {
if ( WEXITSTATUS(childstatus) == 0 )
return OK ;
printf("%s: failed with exit status %d\n",
argv[PGMARG],(int)WEXITSTATUS(childstatus));
return FAILED ;
}
if ( WIFSIGNALED(childstatus) ) {
printf("@DEAD@\n%s: got %s\n",argv[PGMARG],
getsigname(WTERMSIG(childstatus)));
return GOTSIGNAL ;
}
printf("\n@UNRESOLVED@\n%s: bizarre return status %d\n",
argv[PGMARG],childstatus);
return TIMEOUT;
}
}
|