Owen Stephens
2018-11-05 20:59:14 UTC
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)?
Running under strace, I can see:
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{SIG_DFL, [], 0}, 8) = 0
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 rt_sigaction(SIGINT, {0x4624a0, [], SA_RESTORER,
0x7fa5770d24b0}, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 read(0, 0x70c1e0, 128) = ? ERESTARTSYS (To be
restarted if SA_RESTART is set)
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
11630 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{0x4624a0, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 rt_sigaction(SIGINT, {0x465920, [], SA_RESTORER,
0x7fa5770d24b0}, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 kill(11630, SIGINT) = 0
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=11630,
si_uid=1000} ---
11630 rt_sigreturn({mask=[]}) = 0
11630 read(0, "\n", 128) = 1
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{0x465920, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 kill(11630, SIGINT) = 0
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=11630,
si_uid=1000} ---
11630 +++ killed by SIGINT +++
Some questions:
1) Why is read call interrupted (I'm assuming that's what the "= ?"
means) the first time the signal is received, but not the second?
2) Why are there two sigaction calls after the first SIGINT (the
second appears to be changing _from_ the default handler)?
3) Why does rt_sigreturn return -1 (with EINTR) the first time, but 0
the second?
4) Why does the kill call (presumably from my handler) show up twice?
Any light that someone can shed on this would be most-gratefully received.
Thanks,
Owen.
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)?
Running under strace, I can see:
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{SIG_DFL, [], 0}, 8) = 0
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 rt_sigaction(SIGINT, {0x4624a0, [], SA_RESTORER,
0x7fa5770d24b0}, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 read(0, 0x70c1e0, 128) = ? ERESTARTSYS (To be
restarted if SA_RESTART is set)
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
11630 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{0x4624a0, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 rt_sigaction(SIGINT, {0x465920, [], SA_RESTORER,
0x7fa5770d24b0}, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 kill(11630, SIGINT) = 0
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=11630,
si_uid=1000} ---
11630 rt_sigreturn({mask=[]}) = 0
11630 read(0, "\n", 128) = 1
11630 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fa5770d24b0},
{0x465920, [], SA_RESTORER, 0x7fa5770d24b0}, 8) = 0
11630 kill(11630, SIGINT) = 0
11630 --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=11630,
si_uid=1000} ---
11630 +++ killed by SIGINT +++
Some questions:
1) Why is read call interrupted (I'm assuming that's what the "= ?"
means) the first time the signal is received, but not the second?
2) Why are there two sigaction calls after the first SIGINT (the
second appears to be changing _from_ the default handler)?
3) Why does rt_sigreturn return -1 (with EINTR) the first time, but 0
the second?
4) Why does the kill call (presumably from my handler) show up twice?
Any light that someone can shed on this would be most-gratefully received.
Thanks,
Owen.