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
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils