On Wed, Apr 2, 2008 at 10:20 AM, Pádraig Brady <[EMAIL PROTECTED]> wrote: > It will always go through though as the kernel will buffer it.
Yes, that introduces some fuzz, but I think the principle remains viable -- the kernel will only buffer so much. Consider the following using a timeout.c modified with the attached patch, and a small Perl program (below) than hangs after 10 seconds: $ time yes | src/timeout -i 2s ./write_then_hang 10 >/dev/null real 0m11.777s user 0m0.656s sys 0m0.068s Bo -- Perl -- #!/usr/bin/perl -w my $n = shift @ARGV || 10; my $s = time; print scalar(<STDIN>) while (time - $s < $n); while(1){ }
diff --git a/src/timeout.c b/src/timeout.c index 7c15f1d..1f44c27 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -75,6 +75,9 @@ # define WTERMSIG(s) ((s) & 0x7F) #endif +/* Size of atomic reads. */ +#define BUFFER_SIZE (16 * 1024) + static int timed_out; static int term_signal = SIGTERM; /* same default as kill command. */ static int monitored_pid; @@ -83,6 +86,7 @@ static char *program_name; static struct option const long_options[] = { {"signal", required_argument, NULL, 's'}, + {"inactivity", no_argument, NULL, 'i'}, {NULL, 0, NULL, 0} }; @@ -144,8 +148,10 @@ Mandatory arguments to long options are mandatory for short options too.\n\ -s, --signal=SIGNAL\n\ specify the signal to be sent on timeout.\n\ SIGNAL may be a name like `HUP' or a number.\n\ - See `kill -l` for a list of signals\n"), stdout); - + See `kill -l` for a list of signals\n\ + -i, --inactivity\n\ + act as a filter and only timeout if NUMBER\n\ + seconds have passed without data flowing.\n"), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\n\ @@ -250,6 +256,8 @@ main (int argc, char **argv) { unsigned long timeout; char signame[SIG2STR_MAX]; + bool inactivity = false; + int pipefds[2]; int c; char *ep; @@ -265,7 +273,7 @@ main (int argc, char **argv) parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION, usage, AUTHORS, (char const *) NULL); - while ((c = getopt_long (argc, argv, "+s:", long_options, NULL)) != -1) + while ((c = getopt_long (argc, argv, "+s:i", long_options, NULL)) != -1) { switch (c) { @@ -274,6 +282,9 @@ main (int argc, char **argv) if (term_signal == -1) usage (ECANCELED); break; + case 'i': + inactivity = true; + break; default: usage (ECANCELED); break; @@ -315,6 +326,12 @@ main (int argc, char **argv) signal (SIGTTIN, SIG_IGN); /* don't sTop if background child needs tty. */ signal (SIGTTOU, SIG_IGN); /* don't sTop if background child needs tty. */ + if (inactivity) + { + if (pipe(pipefds) == -1) + perror ("pipe"); + } + monitored_pid = fork (); if (monitored_pid == -1) { @@ -325,6 +342,13 @@ main (int argc, char **argv) { /* child */ int exit_status; + if (inactivity) + { + close (pipefds[1]); + close (STDIN_FILENO); + dup2 (pipefds[0], STDIN_FILENO); + } + /* exec doesn't reset SIG_IGN -> SIG_DFL. */ signal (SIGTTIN, SIG_DFL); signal (SIGTTOU, SIG_DFL); @@ -342,6 +366,21 @@ main (int argc, char **argv) alarm ((unsigned int) timeout); + if (inactivity) + { + int bytes_read; + char buf[BUFFER_SIZE]; + close (pipefds[0]); + close (STDOUT_FILENO); + dup2 (pipefds[1], STDOUT_FILENO); + while ((bytes_read = read(STDIN_FILENO, buf, BUFFER_SIZE)) > 0) + { + if ((write(STDOUT_FILENO, buf, bytes_read)) == -1) + perror ("write"); + alarm ((unsigned int) timeout); + } + } + /* We're just waiting for a single process here, so wait() suffices. * Note the signal() calls above on linux and BSD at least, essentially * call the lower level sigaction() with the SA_RESTART flag set, which
_______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils