[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-wget] Timeouts too long?
From: |
Paul McFerrin |
Subject: |
Re: [Bug-wget] Timeouts too long? |
Date: |
Sat, 03 Oct 2009 03:19:56 -0400 |
User-agent: |
Thunderbird 2.0.0.23 (Windows/20090812) |
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-----