mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-20 18:56:39 +02:00
env: new options --{default,ignore,block}-signal[=SIG]
New options to set signal handlers for the command being executed. --block-signal suggested by Paul Eggert in http://bugs.gnu.org/34488#71 --default-signal is useful to overcome the POSIX limitation that shell must not override inherited signal state, e.g. the second 'trap' here is a no-op: trap '' PIPE && sh -c 'trap - PIPE ; seq inf | head -n1' Instead use: trap '' PIPE && sh -c 'env --default-signal=PIPE seq inf | head -n1' Similarly, the following will prevent CTRL-C from terminating the program: env --ignore-signal=INT seq inf > /dev/null See https://bugs.gnu.org/34488#8 * NEWS: Mention new options. * doc/coreutils.texi (env invocation): Document new options. * man/env.x: Add example of --default-signal=SIG usage. (SEE ALSO): Mention sigprocmask. * src/env.c (signals): New global variable. (longopts): Add new options. (usage): Print new options. (parse_signal_params): Parse comma-separated list of signals, store in signals variable. (reset_signal_handlers): Set each signal to SIG_DFL/SIG_IGN. (parse_block_signal_params): Parse command-line options. (set_signal_proc_mask): Call sigprocmask to block/unblock signals. (main): Process new options. * src/local.mk (src_env_SOURCES): Add operand2sig.c. * tests/misc/env-signal-handler.sh: New test. * tests/local.mk (all_tests): Add new test.
This commit is contained in:
committed by
Pádraig Brady
parent
186896d65f
commit
95adadd9a4
3
NEWS
3
NEWS
@@ -84,6 +84,9 @@ GNU coreutils NEWS -*- outline -*-
|
||||
test now supports the '-N FILE' unary operator (like e.g. bash) to check
|
||||
whether FILE exists and has been modified since it was last read.
|
||||
|
||||
env now supports '--default-signal[=SIG]', '--ignore-signal[=SIG]', and
|
||||
'--block-signal[=SIG], to setup signal handling before executing a program.
|
||||
|
||||
** New commands
|
||||
|
||||
basenc is added to complement existing base64,base32 commands,
|
||||
|
||||
@@ -17246,6 +17246,64 @@ chroot /chroot env --chdir=/srv true
|
||||
env --chdir=/build FOO=bar timeout 5 true
|
||||
@end example
|
||||
|
||||
@item --default-signal[=@var{sig}]
|
||||
Unblock and reset signal @var{sig} to its default signal handler.
|
||||
Without @var{sig} all known signals are unblocked and reset to their defaults.
|
||||
Multiple signals can be comma-separated. The following command runs
|
||||
@command{seq} with SIGINT and SIGPIPE set to their default
|
||||
(which is to terminate the program):
|
||||
|
||||
@example
|
||||
env --default-signal=PIPE,INT seq 1000 | head -n1
|
||||
@end example
|
||||
|
||||
In the following example, we see how this is not
|
||||
possible to do with traditional shells.
|
||||
Here the first trap command sets SIGPIPE to ignore.
|
||||
The second trap command ostensibly sets it back to its default,
|
||||
but POSIX mandates that the shell must not change inherited
|
||||
state of the signal - so it is a no-op.
|
||||
|
||||
@example
|
||||
trap '' PIPE && sh -c 'trap - PIPE ; seq inf | head -n1'
|
||||
@end example
|
||||
|
||||
Using @option{--default-signal=PIPE} we can
|
||||
ensure the signal handling is set to its default behavior:
|
||||
|
||||
@example
|
||||
trap '' PIPE && sh -c 'env --default-signal=PIPE seq inf | head -n1'
|
||||
@end example
|
||||
|
||||
|
||||
@item --ignore-signal[=@var{sig}]
|
||||
Ignore signal @var{sig} when running a program. Without @var{sig} all
|
||||
known signals are set to ignore. Multiple signals can be
|
||||
comma-separated. The following command runs @command{seq} with SIGINT set
|
||||
to be ignored - pressing @kbd{Ctrl-C} will not terminate it:
|
||||
|
||||
@example
|
||||
env --ignore-signal=INT seq inf > /dev/null
|
||||
@end example
|
||||
|
||||
@samp{SIGCHLD} is special, in that @option{--ignore-signal=CHLD} might have
|
||||
no effect (POSIX says it's unspecified).
|
||||
|
||||
Most operating systems do not allow ignoring @samp{SIGKILL}, @samp{SIGSTOP}
|
||||
(and possibly other signals). Attempting to ignore these signals will fail.
|
||||
|
||||
Multiple (and contradictory) @option{--default-signal=SIG} and
|
||||
@option{--ignore-signal=SIG} options are processed left-to-right,
|
||||
with the latter taking precedence. In the following example, @samp{SIGPIPE} is
|
||||
set to default while @samp{SIGINT} is ignored:
|
||||
|
||||
@example
|
||||
env --default-signal=INT,PIPE --ignore-signal=INT
|
||||
@end example
|
||||
|
||||
@item --block-signal[=@var{sig}]
|
||||
Block signal(s) @var{sig} from being delivered.
|
||||
|
||||
@item -v
|
||||
@itemx --debug
|
||||
@opindex -v
|
||||
|
||||
28
man/env.x
28
man/env.x
@@ -37,3 +37,31 @@ parameter the script will likely fail with:
|
||||
.RE
|
||||
.PP
|
||||
See the full documentation for more details.
|
||||
.PP
|
||||
.SS "\-\-default-signal[=SIG]" usage
|
||||
This option allows setting a signal handler to its default
|
||||
action, which is not possible using the traditional shell
|
||||
trap command. The following example ensures that seq
|
||||
will be terminated by SIGPIPE no matter how this signal
|
||||
is being handled in the process invoking the command.
|
||||
|
||||
.PP
|
||||
.RS
|
||||
.nf
|
||||
sh \-c 'env \-\-default-signal=PIPE seq inf | head \-n1'
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
|
||||
[NOTES]
|
||||
POSIX's exec(2) pages says:
|
||||
.RS
|
||||
"many existing applications wrongly assume that they start with certain
|
||||
signals set to the default action and/or unblocked.... Therefore, it is best
|
||||
not to block or ignore signals across execs without explicit reason to do so,
|
||||
and especially not to block signals across execs of arbitrary (not closely
|
||||
cooperating) programs."
|
||||
.RE
|
||||
|
||||
[SEE ALSO]
|
||||
sigaction(2), sigprocmask(2), signal(7)
|
||||
|
||||
235
src/env.c
235
src/env.c
@@ -21,12 +21,15 @@
|
||||
#include <sys/types.h>
|
||||
#include <getopt.h>
|
||||
#include <c-ctype.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include "system.h"
|
||||
#include "die.h"
|
||||
#include "error.h"
|
||||
#include "operand2sig.h"
|
||||
#include "quote.h"
|
||||
#include "sig2str.h"
|
||||
|
||||
/* The official name of this program (e.g., no 'g' prefix). */
|
||||
#define PROGRAM_NAME "env"
|
||||
@@ -48,14 +51,45 @@ static bool dev_debug;
|
||||
static char *varname;
|
||||
static size_t vnlen;
|
||||
|
||||
/* Possible actions on each signal. */
|
||||
enum SIGNAL_MODE {
|
||||
UNCHANGED = 0,
|
||||
DEFAULT, /* Set to default handler (SIG_DFL). */
|
||||
DEFAULT_NOERR, /* ditto, but ignore sigaction(2) errors. */
|
||||
IGNORE, /* Set to ignore (SIG_IGN). */
|
||||
IGNORE_NOERR /* ditto, but ignore sigaction(2) errors. */
|
||||
};
|
||||
static enum SIGNAL_MODE signals[SIGNUM_BOUND + 1];
|
||||
|
||||
/* Set of signals to block. */
|
||||
static sigset_t block_signals;
|
||||
|
||||
/* Set of signals to unblock. */
|
||||
static sigset_t unblock_signals;
|
||||
|
||||
/* Whether signal mask adjustment requested. */
|
||||
static bool sig_mask_changed;
|
||||
|
||||
static char const shortopts[] = "+C:iS:u:v0 \t";
|
||||
|
||||
/* For long options that have no equivalent short option, use a
|
||||
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
|
||||
enum
|
||||
{
|
||||
DEFAULT_SIGNAL_OPTION = CHAR_MAX + 1,
|
||||
IGNORE_SIGNAL_OPTION,
|
||||
BLOCK_SIGNAL_OPTION,
|
||||
};
|
||||
|
||||
static struct option const longopts[] =
|
||||
{
|
||||
{"ignore-environment", no_argument, NULL, 'i'},
|
||||
{"null", no_argument, NULL, '0'},
|
||||
{"unset", required_argument, NULL, 'u'},
|
||||
{"chdir", required_argument, NULL, 'C'},
|
||||
{"default-signal", optional_argument, NULL, DEFAULT_SIGNAL_OPTION},
|
||||
{"ignore-signal", optional_argument, NULL, IGNORE_SIGNAL_OPTION},
|
||||
{"block-signal", optional_argument, NULL, BLOCK_SIGNAL_OPTION},
|
||||
{"debug", no_argument, NULL, 'v'},
|
||||
{"split-string", required_argument, NULL, 'S'},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
@@ -90,6 +124,17 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
|
||||
fputs (_("\
|
||||
-S, --split-string=S process and split S into separate arguments;\n\
|
||||
used to pass multiple arguments on shebang lines\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
--block-signal[=SIG] block delivery of SIG signal(s) to COMMAND\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
--default-signal[=SIG] reset handling of SIG signal(s) to the default\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
--ignore-signal[=SIG] set handling of SIG signals(s) to do nothing\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-v, --debug print verbose information for each processing step\n\
|
||||
"), stdout);
|
||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
||||
@@ -97,6 +142,12 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
|
||||
fputs (_("\
|
||||
\n\
|
||||
A mere - implies -i. If no COMMAND, print the resulting environment.\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
\n\
|
||||
SIG may be a signal name like 'PIPE', or a signal number like '13'.\n\
|
||||
Without SIG, all known signals are included. Multiple signals can be\n\
|
||||
comma-separated.\n\
|
||||
"), stdout);
|
||||
emit_ancillary_info (PROGRAM_NAME);
|
||||
}
|
||||
@@ -525,6 +576,176 @@ parse_split_string (const char* str, int /*out*/ *orig_optind,
|
||||
*orig_optind = 0; /* tell getopt to restart from first argument */
|
||||
}
|
||||
|
||||
static void
|
||||
parse_signal_action_params (const char* optarg, bool set_default)
|
||||
{
|
||||
char signame[SIG2STR_MAX];
|
||||
char *opt_sig;
|
||||
char *optarg_writable;
|
||||
|
||||
if (! optarg)
|
||||
{
|
||||
/* without an argument, reset all signals.
|
||||
Some signals cannot be set to ignore or default (e.g., SIGKILL,
|
||||
SIGSTOP on most OSes, and SIGCONT on AIX.) - so ignore errors. */
|
||||
for (int i = 1 ; i <= SIGNUM_BOUND; i++)
|
||||
if (sig2str (i, signame) == 0)
|
||||
signals[i] = set_default ? DEFAULT_NOERR : IGNORE_NOERR;
|
||||
return;
|
||||
}
|
||||
|
||||
optarg_writable = xstrdup (optarg);
|
||||
|
||||
opt_sig = strtok (optarg_writable, ",");
|
||||
while (opt_sig)
|
||||
{
|
||||
int signum = operand2sig (opt_sig, signame);
|
||||
/* operand2sig accepts signal 0 (EXIT) - but we reject it. */
|
||||
if (signum == 0)
|
||||
error (0, 0, _("%s: invalid signal"), quote (opt_sig));
|
||||
if (signum <= 0)
|
||||
usage (exit_failure);
|
||||
|
||||
signals[signum] = set_default ? DEFAULT : IGNORE;
|
||||
|
||||
opt_sig = strtok (NULL, ",");
|
||||
}
|
||||
|
||||
free (optarg_writable);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_signal_handlers (void)
|
||||
{
|
||||
for (int i = 1; i <= SIGNUM_BOUND; i++)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
if (signals[i] == UNCHANGED)
|
||||
continue;
|
||||
|
||||
bool ignore_errors = (signals[i] == DEFAULT_NOERR
|
||||
|| signals[i] == IGNORE_NOERR);
|
||||
|
||||
bool set_to_default = (signals[i] == DEFAULT
|
||||
|| signals[i] == DEFAULT_NOERR);
|
||||
|
||||
int sig_err = sigaction (i, NULL, &act);
|
||||
|
||||
if (sig_err && !ignore_errors)
|
||||
die (EXIT_CANCELED, errno,
|
||||
_("failed to get signal action for signal %d"), i);
|
||||
|
||||
if (! sig_err)
|
||||
{
|
||||
act.sa_handler = set_to_default ? SIG_DFL : SIG_IGN;
|
||||
|
||||
if ((sig_err = sigaction (i, &act, NULL)) && !ignore_errors)
|
||||
die (EXIT_CANCELED, errno,
|
||||
_("failed to set signal action for signal %d"), i);
|
||||
}
|
||||
|
||||
if (dev_debug)
|
||||
{
|
||||
char signame[SIG2STR_MAX];
|
||||
sig2str (i, signame);
|
||||
devmsg ("Reset signal %s (%d) to %s%s\n",
|
||||
signame, i,
|
||||
set_to_default ? "DEFAULT" : "IGNORE",
|
||||
sig_err ? " (failure ignored)" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_block_signal_params (const char* optarg, bool block)
|
||||
{
|
||||
char signame[SIG2STR_MAX];
|
||||
char *opt_sig;
|
||||
char *optarg_writable;
|
||||
|
||||
if (! optarg)
|
||||
{
|
||||
/* without an argument, reset all signals. */
|
||||
sigfillset (block ? &block_signals : &unblock_signals);
|
||||
sigemptyset (block ? &unblock_signals : &block_signals);
|
||||
}
|
||||
else if (! sig_mask_changed)
|
||||
{
|
||||
/* Initialize the sets. */
|
||||
sigemptyset (&block_signals);
|
||||
sigemptyset (&unblock_signals);
|
||||
}
|
||||
|
||||
sig_mask_changed = true;
|
||||
|
||||
if (! optarg)
|
||||
return;
|
||||
|
||||
optarg_writable = xstrdup (optarg);
|
||||
|
||||
opt_sig = strtok (optarg_writable, ",");
|
||||
while (opt_sig)
|
||||
{
|
||||
int signum = operand2sig (opt_sig, signame);
|
||||
/* operand2sig accepts signal 0 (EXIT) - but we reject it. */
|
||||
if (signum == 0)
|
||||
error (0, 0, _("%s: invalid signal"), quote (opt_sig));
|
||||
if (signum <= 0)
|
||||
usage (exit_failure);
|
||||
|
||||
sigaddset (block ? &block_signals : &unblock_signals, signum);
|
||||
sigdelset (block ? &unblock_signals : &block_signals, signum);
|
||||
|
||||
opt_sig = strtok (NULL, ",");
|
||||
}
|
||||
|
||||
free (optarg_writable);
|
||||
}
|
||||
|
||||
static void
|
||||
set_signal_proc_mask (void)
|
||||
{
|
||||
/* Get the existing signal mask */
|
||||
sigset_t set;
|
||||
const char *debug_act;
|
||||
|
||||
sigemptyset (&set);
|
||||
|
||||
if (sigprocmask (0, NULL, &set))
|
||||
die (EXIT_CANCELED, errno, _("failed to get signal process mask"));
|
||||
|
||||
for (int i = 1; i <= SIGNUM_BOUND; i++)
|
||||
{
|
||||
if (sigismember (&block_signals, i))
|
||||
{
|
||||
sigaddset (&set, i);
|
||||
debug_act = "BLOCK";
|
||||
}
|
||||
else if (sigismember (&unblock_signals, i))
|
||||
{
|
||||
sigdelset (&set, i);
|
||||
debug_act = "UNBLOCK";
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_act = NULL;
|
||||
}
|
||||
|
||||
if (dev_debug && debug_act)
|
||||
{
|
||||
char signame[SIG2STR_MAX];
|
||||
sig2str (i, signame);
|
||||
devmsg ("signal %s (%d) mask set to %s\n",
|
||||
signame, i, debug_act);
|
||||
}
|
||||
}
|
||||
|
||||
if (sigprocmask (SIG_SETMASK, &set, NULL))
|
||||
die (EXIT_CANCELED, errno, _("failed to set signal process mask"));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -558,6 +779,16 @@ main (int argc, char **argv)
|
||||
case '0':
|
||||
opt_nul_terminate_output = true;
|
||||
break;
|
||||
case DEFAULT_SIGNAL_OPTION:
|
||||
parse_signal_action_params (optarg, true);
|
||||
parse_block_signal_params (optarg, false);
|
||||
break;
|
||||
case IGNORE_SIGNAL_OPTION:
|
||||
parse_signal_action_params (optarg, false);
|
||||
break;
|
||||
case BLOCK_SIGNAL_OPTION:
|
||||
parse_block_signal_params (optarg, true);
|
||||
break;
|
||||
case 'C':
|
||||
newdir = optarg;
|
||||
break;
|
||||
@@ -633,6 +864,10 @@ main (int argc, char **argv)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
reset_signal_handlers ();
|
||||
if (sig_mask_changed)
|
||||
set_signal_proc_mask ();
|
||||
|
||||
if (newdir)
|
||||
{
|
||||
devmsg ("chdir: %s\n", quoteaf (newdir));
|
||||
|
||||
@@ -356,6 +356,7 @@ src_coreutils_SOURCES = src/coreutils.c
|
||||
|
||||
src_cp_SOURCES = src/cp.c $(copy_sources) $(selinux_sources)
|
||||
src_dir_SOURCES = src/ls.c src/ls-dir.c
|
||||
src_env_SOURCES = src/env.c src/operand2sig.c
|
||||
src_vdir_SOURCES = src/ls.c src/ls-vdir.c
|
||||
src_id_SOURCES = src/id.c src/group-list.c
|
||||
src_groups_SOURCES = src/groups.c src/group-list.c
|
||||
|
||||
@@ -240,6 +240,7 @@ all_tests = \
|
||||
tests/fmt/goal-option.sh \
|
||||
tests/misc/echo.sh \
|
||||
tests/misc/env.sh \
|
||||
tests/misc/env-signal-handler.sh \
|
||||
tests/misc/ptx.pl \
|
||||
tests/misc/test.pl \
|
||||
tests/misc/seq.pl \
|
||||
|
||||
131
tests/misc/env-signal-handler.sh
Executable file
131
tests/misc/env-signal-handler.sh
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/bin/sh
|
||||
# Test env --default-signal=PIPE feature.
|
||||
|
||||
# Copyright (C) 2019 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ env seq test timeout
|
||||
trap_sigpipe_or_skip_
|
||||
|
||||
# Paraphrasing http://bugs.gnu.org/34488#8:
|
||||
# POSIX requires that sh started with an inherited ignored SIGPIPE must
|
||||
# silently ignore all attempts from within the shell to restore SIGPIPE
|
||||
# handling to child processes of the shell:
|
||||
#
|
||||
# $ (trap '' PIPE; bash -c 'trap - PIPE; seq inf | head -n1')
|
||||
# 1
|
||||
# seq: write error: Broken pipe
|
||||
#
|
||||
# With 'env --default-signal=PIPE', the signal handler can be reset to its
|
||||
# default.
|
||||
|
||||
# Baseline Test - default signal handler
|
||||
# --------------------------------------
|
||||
# Ensure this results in a "broken pipe" error (the first 'trap'
|
||||
# sets SIGPIPE to ignore, and the second 'trap' becomes a no-op instead
|
||||
# of resetting SIGPIPE to its default). Upon a SIGPIPE 'seq' will not be
|
||||
# terminated, instead its write(2) call will return an error.
|
||||
(trap '' PIPE; $SHELL -c 'trap - PIPE; seq 999999 2>err1t | head -n1 > out1')
|
||||
|
||||
# The exact broken pipe message depends on the operating system, just ensure
|
||||
# there was a 'write error' message in stderr:
|
||||
sed 's/^\(seq: write error:\) .*/\1/' err1t > err1 || framework_failure_
|
||||
|
||||
printf "1\n" > exp-out || framework_failure_
|
||||
printf "seq: write error:\n" > exp-err1 || framework_failure_
|
||||
|
||||
compare exp-out out1 || framework_failure_
|
||||
compare exp-err1 err1 || framework_failure_
|
||||
|
||||
|
||||
# env test - default signal handler
|
||||
# ---------------------------------
|
||||
# With env resetting the signal handler to its defaults, there should be no
|
||||
# error message (because the default SIGPIPE action is to terminate the
|
||||
# 'seq' program):
|
||||
(trap '' PIPE;
|
||||
env --default-signal=PIPE \
|
||||
$SHELL -c 'trap - PIPE; seq 999999 2>err2 | head -n1 > out2')
|
||||
|
||||
compare exp-out out2 || fail=1
|
||||
compare /dev/null err2 || fail=1
|
||||
|
||||
# env test - default signal handler (3)
|
||||
# -------------------------------------
|
||||
# Repeat the previous test, using --default-signal with no signal names,
|
||||
# i.e., all signals.
|
||||
(trap '' PIPE;
|
||||
env --default-signal \
|
||||
$SHELL -c 'trap - PIPE; seq 999999 2>err4 | head -n1 > out4')
|
||||
|
||||
compare exp-out out4 || fail=1
|
||||
compare /dev/null err4 || fail=1
|
||||
|
||||
# env test - block signal handler
|
||||
env --block-signal true || fail=1
|
||||
|
||||
# Baseline test - ignore signal handler
|
||||
# -------------------------------------
|
||||
# Kill 'sleep' after 1 second with SIGINT - it should terminate (as SIGINT's
|
||||
# default action is to terminate a program).
|
||||
# (The first 'env' is just to ensure timeout is not the shell's built-in.)
|
||||
env timeout --verbose --kill-after=.1 --signal=INT .1 \
|
||||
sleep 10 > /dev/null 2>err5
|
||||
|
||||
printf "timeout: sending signal INT to command 'sleep'\n" > exp-err5 \
|
||||
|| framework_failure_
|
||||
|
||||
compare exp-err5 err5 || fail=1
|
||||
|
||||
|
||||
# env test - ignore signal handler
|
||||
# --------------------------------
|
||||
# Use env to silence (ignore) SIGINT - "seq" should continue running
|
||||
# after timeout sends SIGINT, and be killed after 1 second using SIGKILL.
|
||||
|
||||
cat>exp-err6 <<EOF
|
||||
timeout: sending signal INT to command 'env'
|
||||
timeout: sending signal KILL to command 'env'
|
||||
EOF
|
||||
|
||||
env timeout --verbose --kill-after=.1 --signal=INT .1 \
|
||||
env --ignore-signal=INT \
|
||||
sleep 10 > /dev/null 2>err6t
|
||||
|
||||
# check only the first two lines from stderr, which are printed by timeout.
|
||||
# (operating systems might add more messages, like "killed").
|
||||
sed -n '1,2p' err6t > err6 || framework_failure_
|
||||
|
||||
compare exp-err6 err6 || fail=1
|
||||
|
||||
|
||||
# env test - ignore signal handler (2)
|
||||
# ------------------------------------
|
||||
# Repeat the previous test with "--ignore-signals" and no signal names,
|
||||
# i.e., all signals.
|
||||
|
||||
env timeout --verbose --kill-after=.1 --signal=INT .1 \
|
||||
env --ignore-signal \
|
||||
sleep 10 > /dev/null 2>err7t
|
||||
|
||||
# check only the first two lines from stderr, which are printed by timeout.
|
||||
# (operating systems might add more messages, like "killed").
|
||||
sed -n '1,2p' err7t > err7 || framework_failure_
|
||||
|
||||
compare exp-err6 err7 || fail=1
|
||||
|
||||
|
||||
Exit $fail
|
||||
Reference in New Issue
Block a user