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

Reply via email to