1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-08-05 08:10:15 +02:00

timeout: add --foreground to support interactive commands

Or more accurately, commands not started from the shell prompt,
that are interactive, or need to receive Ctrl-C etc. from the terminal.

* doc/coreutils.texi (timeout invocation): Document --foreground.
* src/timeout.c (main): Set the foreground flag and don't create
a separate group.
(cleanup): Only send a signal directly to the monitored command
when the foreground flag is set.
(usage): Describe --foreground.
* tests/misc/timeout-group: Add a new test.
* tests/Makefile.am: Reference new test.
NEWS: Mention the new option.

Reported by Shay Shimony
Analysis by Alan Curry
Fix suggested by Paul Eggert
This commit is contained in:
Pádraig Brady
2011-07-06 23:17:10 +01:00
parent 28a7fb52bc
commit 4496c94091
5 changed files with 108 additions and 8 deletions
+4
View File
@@ -33,6 +33,10 @@ GNU coreutils NEWS -*- outline -*-
tool exit non-zero for any invalid input line, rather than just warning.
This also affects sha1sum, sha224sum, sha384sum and sha512sum.
timeout accepts a new --foreground option, to support commands not started
directly from a shell prompt, where the command is interactive or needs to
receive signals initiated from the terminal.
** Improvements
shuf outputs small subsets of large permutations much more efficiently.
+17
View File
@@ -15658,6 +15658,23 @@ The program accepts the following options. Also see @ref{Common options}.
Options must precede operands.
@table @samp
@itemx --foreground
@opindex --foreground
Don't create a separate background program group, so that
the managed @var{command} can use the foreground TTY normally.
This is needed to support timing out commands not started
directly from an interactive shell, in two situations.
@enumerate
@item
@var{command} is interactive and needs to read from the terminal for example
@item
the user wants to support sending signals directly to @var{command}
from the terminal (like Ctrl-C for example)
@end enumerate
Note in this mode of operation, any children of @var{command}
will not be timed out.
@item -k @var{duration}
@itemx --kill-after=@var{duration}
@opindex -k
+28 -8
View File
@@ -67,11 +67,19 @@ static int term_signal = SIGTERM; /* same default as kill command. */
static int monitored_pid;
static int sigs_to_ignore[NSIG]; /* so monitor can ignore sigs it resends. */
static unsigned long kill_after;
static bool foreground; /* whether to use another program group. */
/* for long options with no corresponding short option, use enum */
enum
{
FOREGROUND_OPTION = CHAR_MAX + 1
};
static struct option const long_options[] =
{
{"kill-after", required_argument, NULL, 'k'},
{"signal", required_argument, NULL, 's'},
{"foreground", no_argument, NULL, FOREGROUND_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -96,6 +104,8 @@ cleanup (int sig)
}
if (monitored_pid)
{
int where = foreground ? monitored_pid : 0;
if (sigs_to_ignore[sig])
{
sigs_to_ignore[sig] = 0;
@@ -108,9 +118,10 @@ cleanup (int sig)
alarm (kill_after);
kill_after = 0; /* Don't let later signals reset kill alarm. */
}
send_sig (0, sig);
send_sig (where, sig);
if (sig != SIGKILL && sig != SIGCONT)
send_sig (0, SIGCONT);
send_sig (where, SIGCONT);
}
else /* we're the child or the child is not exec'd yet. */
_exit (128 + sig);
@@ -134,13 +145,17 @@ Start COMMAND, and kill it if still running after DURATION.\n\
Mandatory arguments to long options are mandatory for short options too.\n\
"), stdout);
fputs (_("\
--foreground\n\
When not running timeout directly from a shell prompt,\n\
allow COMMAND to read from the TTY and receive TTY signals.\n\
In this mode, children of COMMAND will not be timed out.\n\
-k, --kill-after=DURATION\n\
also send a KILL signal if COMMAND is still running\n\
this long after the initial signal was sent.\n\
also send a KILL signal if COMMAND is still running\n\
this long after the initial signal was sent.\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);
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);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -266,6 +281,10 @@ main (int argc, char **argv)
usage (EXIT_CANCELED);
break;
case FOREGROUND_OPTION:
foreground = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -287,7 +306,8 @@ main (int argc, char **argv)
Note we don't just put the child in a separate group as
then we would need to worry about foreground and background groups
and propagating signals between them. */
setpgid (0, 0);
if (!foreground)
setpgid (0, 0);
/* Setup handlers before fork() so that we
handle any signals caused by child, without races. */
+1
View File
@@ -277,6 +277,7 @@ TESTS = \
misc/tee-dash \
misc/test-diag \
misc/timeout \
misc/timeout-group \
misc/timeout-parameters \
misc/tr \
misc/tr-case-class \
+58
View File
@@ -0,0 +1,58 @@
#!/bin/sh
# test program group handling
# Copyright (C) 2011 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
. "${srcdir=.}/init.sh"; path_prepend_ ../src
print_ver_ timeout
# construct a program group hierarchy as follows:
# timeout-group - foreground group
# group.sh - separate group
# timeout.cmd - same group as group.sh
#
# We then send a SIGINT to the "separate group"
# to simulate what happens when a Ctrl-C
# is sent to the foreground group.
setsid true || skip_ "setsid required to control groups"
cat > timeout.cmd <<\EOF
#!/bin/sh
trap 'touch int.received; exit' INT
touch timeout.running
sleep 10
EOF
chmod a+x timeout.cmd
cat > group.sh <<\EOF
#!/bin/sh
timeout --foreground 5 ./timeout.cmd&
wait
EOF
chmod a+x group.sh
# Start above script in its own group.
# We could use timeout for this, but that assumes an implementation.
setsid ./group.sh &
until test -e timeout.running; do sleep .1; done
# Simulate a Ctrl-C to the group to test timely exit
# Note dash doesn't support signalling groups (a leading -)
env kill -INT -- -$!
wait
test -e int.received || fail=1
Exit $fail