[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] trap not invoked after resuming read from trap
From: |
Owen Stephens |
Subject: |
Re: [Help-bash] trap not invoked after resuming read from trap |
Date: |
Wed, 7 Nov 2018 01:09:39 +0000 |
On Tue, Nov 6, 2018 at 9:19 PM Chet Ramey <address@hidden> wrote:
>
> Here's what happens. The shell receives SIGINT and sets a flag noting it.
> The SIGINT interrupts read(2), and the shell notices the -1/EINTR and runs
> the SIGINT trap. That's not strictly the way things should happen, since
> traps are run at command boundaries and the read builtin doesn't complete,
> but it is what people expect.
When you say "That's not strictly the way things should happen" are you
referring to the manual:
https://www.gnu.org/software/bash/manual/bash.html#Signals
specifically, "If Bash is waiting for a command to complete and receives a
signal for which a trap has been set, the trap will not be executed until the
command completes"? It would indeed be strange if SIGINT didn't interrupt a
pending read.
I note that the manual 6.11 Bash POSIX Mode section says "The read builtin may
be interrupted by a signal for which a trap has been set. If Bash receives a
trapped signal while executing read, the trap handler executes and read returns
an exit status greater than 128." and indeed, using --posix, my script performs
as I originally expected, namely exiting with 130 after a single Ctrl-C. What
is the reason for behaving differently without --posix in this regard?
> There are a couple of things to do, all involving checking for terminating
> signals before resuming the read. I'll do one of them.
Will this mean that my example _will_ exit after a single Ctrl-c? What are the
couple of things to do, and what behaviour will they change?
Thanks,
Owen.
On Tue, Nov 6, 2018 at 9:19 PM Chet Ramey <address@hidden> wrote:
>
> On 11/5/18 3:59 PM, Owen Stephens wrote:
> > Hi,
> >
> > I'm trying to understand the behaviour of the following simple script
> > in response to SIGINT:
> >
> > $ cat read_sigint.sh
> > #!/usr/bin/env bash
> > trap 'trap - INT; kill -INT $$' INT
> > while read -r line; do echo "Read <$line>"; done
> >
> > I expected this script to (upon receiving SIGINT) reset the trap to
> > the default handler and immediately exit due to receiving SIGINT from
> > itself (as per https://www.cons.org/cracauer/sigint.html). However,
> > the process doesn't immediately exit: if I run this process
> > interactively and hit Ctrl-c I have to hit Enter, for the process to
> > exit. Why is this (presumably it's so the read call returns, but why
> > has it resumed)?
>
> Here's what happens. The shell receives SIGINT and sets a flag noting it.
> The SIGINT interrupts read(2), and the shell notices the -1/EINTR and runs
> the SIGINT trap. That's not strictly the way things should happen, since
> traps are run at command boundaries and the read builtin doesn't complete,
> but it is what people expect.
>
> The trap handler resets the signal disposition to SIG_DFL, which causes the
> shell to set the SIGINT handler to an internal function that will allow the
> shell to clean up after itself before terminating. The subsequent SIGINT
> from the trap action sets a flag that tells the shell to call this function
> at its next opportunity. We're still running in the trap handler, not the
> read.
>
> The trap handler returns, and resumes the read. There is nothing to
> interrupt the read, and the shell won't check for signals and run handlers
> until it returns. That explains the behavior you observed.
>
> There are a couple of things to do, all involving checking for terminating
> signals before resuming the read. I'll do one of them.
>
> Chet
>
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
> ``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, UTech, CWRU address@hidden http://tiswww.cwru.edu/~chet/