This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Bug-wget] Timeouts too long?


I've written a small & nifty program that will terminate a command line after N seconds. It was written nearly 18 years ago and has served me very well. I'm not saying that you always live with bad program design, but having a solution is quite nice. The usage is:
tcmd [-s {sig#}] [-t secs] [-x] cmd args ...


Ejoy. This one is on me.

Here is the source, compile for yourselves.
----------------------------------------------------------------
#ident  "@(#)tcmd.c - NCP 1.1  08/28/91  -  PEM"

/*
       Execute the command line and terminate if it does
       not complete within a specified time limit.

       Usage:
               tcmd [-s signal] [-t secs] [-x] cmd args ...

       Upon timeout, signal "signal" (default is SIGTERM) is
       sent to all children in child process group.

       Exit codes:
                 0 = success
               254 = timed-out
               253 = execvp() failed for cmd
               252 = fork() failed
               251 = usage() exit
               128-146 = cmd terminated with signal 'sig - 127'
               all_others = exit status of "cmd"

Author: Paul E. McFerrin, 55821, Aug 27, 1991

*/


#include <stdio.h> #include <signal.h> #include <errno.h>

extern int errno, optind;
extern char *optarg;
int     tlimit;         /* allowed time limit */
int     ksig;           /* signal to use to terminate */
int     timeout();      /* alarm clock signal catcher */
int     timedout;       /* > 0 if execution timed out */
int     childpid;       /* pid of chil process */
char    *cmd;           /* the name of our process, argv[0] */

main( argc, argv )
int     argc;
char    *argv[];
{
       int     xflag, opt, i, status, ws, myuid;

       myuid = getuid();       /* remember our real-uid */
       cmd = *argv;            /* save our name is global area */
       tlimit = 30;    /* default 30 seconds */
       ksig = SIGTERM; /* default terminate signal */
       xflag=0;
       timedout = 0;
       if( argc <= 1 ) usage();        /* no return */

while ( (opt = getopt(argc, argv, "s:t:x")) != EOF ) {
switch (opt) {
case 'x' :
xflag = 1;
break;
case 't' :
tlimit = atoi(optarg);
if( tlimit <= 0) {
fprintf(stderr, "%s: time limit must be > 0\n",
cmd);
usage();
}
break;
case 's' :
ksig = atoi(optarg);
if( ksig < 1 || ksig > SIGUSR2 ) {
fprintf(stderr, "%s: bad signal number: %s\n",
cmd, optarg);
usage();
}
break;
default:
usage();
}
}
if( xflag ) {
fprintf(stderr, "+ ");
for(i=optind; i<argc; i++) {
fprintf(stderr, "%s ", argv[i]);
}
fprintf(stderr, "\n");
}
childpid = fork();
switch (childpid) {
case -1 :
fprintf(stderr, "%s: can not fork()\n", cmd);
perror("");
exit(252);
break;
case 0 : /* child */
break;
default : /* parent */
signal(SIGALRM, timeout);
signal(SIGHUP, timeout);
signal(SIGINT, timeout);
signal(SIGTERM, timeout);
signal(SIGQUIT, timeout);
signal(SIGPIPE, timeout);
signal(SIGUSR1, timeout);
signal(SIGUSR2, timeout);
alarm(tlimit);
do {
ws = wait(&status);
} while ( (ws != childpid) && (ws < 0 && errno == EINTR) );
alarm(0);
if( timedout == SIGALRM ) {
if( xflag ) fprintf(stderr,
"%s: Command timed-out\n", cmd);
exit(254);
}
exit( (status & 255) ? status + 127 : status >> 8);
break;
}
/*
* At this point, the child is executing this code. Become
* a process group leader to that our parent can kill all
* of our processes not known by our parent.
*/
setuid(myuid); /* give up root access */
setpgrp();
execvp( argv[optind], &argv[optind] );
fprintf( stderr, "%s: '%s' - not executed. ", cmd, argv[optind] );
perror( "" );
exit( 253 );
}


usage()
{
fprintf( stderr, "Usage: %s [-t secs] [-s signal] [-x] command [ arg ..
. ]\n", cmd );
exit(251);
}


/*
*      signal trap handler.  If signal receive is SIGALRM then
*      we send "ksig".  All other signals are sent as is to the
*      child process group leader.  This permits hangups,
*      interrupts, and quits, .... to be received by the new
*      process group.
*/
timeout(sig)
int     sig;
{
       timedout = sig == SIGALRM ? ksig : sig;
       if( childpid < 3 ) return;      /* fail safe protection */
       kill(-childpid, timedout);
       return;
}


- Paul


Micah Cowan wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

With Wget's default of 20 tries, and 900-second timeouts, the following
bug report notes that Wget can sit on a download attempt for a total of
2.5 hours (actually, my math puts it at 5).

https://savannah.gnu.org/bugs/index.php?27141

Obviously, we can adjust these settings in wgetrc, but should that be
necessary? Are people happy with the current timeout settings, and if
not, what are some proposed better values?

- --
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer.
Maintainer of GNU Wget and GNU Teseq
http://micah.cowan.name/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkrGRlcACgkQ7M8hyUobTrG18gCfTHKEcrdXrG/An2g5IM9ZPyTK
uK0An1vJXqsSF98X8vO7MRsR+f2197Tf
=SJkz
-----END PGP SIGNATURE-----




-- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]