timeout command

Tom Christiansen tchrist at convex.com
Mon Oct 2 04:46:31 AEST 1989


It is occasionally useful to set a timeout on a command that
would otherwise hang or run forever.  Instead of building a timeout
into each command, the UNIX philosophy would be to build a tool
to do the timeout for you, so here it is.  It's pretty easy
to write, and has surely been done many times before, but I didn't
have one handy when I needed it, so here it is.


#include <stdio.h>
#include <signal.h>
#include <sysexits.h>
#include <sys/wait.h>

int pid,count;
union wait status;
int bang();
char **commands;

main(ac,av) 
    char **av;
{
    if (ac < 3) {
usage:  fprintf (stderr, "usage: %s seconds command\n",*av);
	exit (EX_USAGE);
    } 
    if ((count=atoi(av[1])) < 1) {
	fprintf (stderr, "seconds (%s) malformed or nonpositive\n",av[1]);
	goto usage;
    } 

    commands = &av[2];
    switch (pid=fork()) {
	default: parent(); 
		 break;
	case 0: child();  
		 /* NOTREACHED */
	case -1: perror("fork"); 
		 exit(EX_OSERR); 
		 /* NOTREACHED */
    } 
    printf("exit status was %d\n",status.w_retcode);
    printf("termsig was %d\n",status.w_termsig);
} 

parent() {
    (void) signal(SIGALRM,bang);
    alarm(count);
    while(wait(&status) != pid) 
	  /* VOID */; 
    if (WIFSIGNALED(status)) 
	exit(-status.w_termsig);
    exit(status.w_retcode);

} 


bang() {
    fprintf(stderr,"Timeout!\n");
    (void) signal(SIGALRM,SIG_DFL);
    (void) kill(pid,SIGTERM);
    if (!kill(pid,0)) {
	sleep(3);
	(void) kill(pid,SIGKILL);
    }
    exit(EX_TEMPFAIL);
} 

child() {
    execvp(*commands,commands);
    perror(*commands);
    _exit(EX_DATAERR);
    /* NOTREACHED */
} 

/* lint output:
 *	timeout.c:
 */

    Tom Christiansen                       {uunet,uiucdcs,sun}!convex!tchrist 
    Convex Computer Corporation                            tchrist at convex.COM
		 "EMACS belongs in <sys/errno.h>: Editor too big!"



More information about the Alt.sources mailing list