mirror of https://github.com/mirror/busybox.git
shell: fix SIGWINCH and SIGCHLD (in hush) interrupting line input, closes 15256
function old new delta record_pending_signo 32 63 +31 lineedit_read_key 231 224 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 31/-7) Total: 24 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>pull/82/head
parent
c2739e11de
commit
93e0898c66
|
@ -2180,7 +2180,8 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
|
|||
* "\xff\n",pause,"ls\n" invalid and thus won't lose "ls".
|
||||
*
|
||||
* If LI_INTERRUPTIBLE, return -1 if got EINTR in poll()
|
||||
* inside read_key, or if bb_got_signal != 0 (IOW: if signal
|
||||
* inside read_key and bb_got_signal became != 0,
|
||||
* or if bb_got_signal != 0 (IOW: if signal
|
||||
* arrived before poll() is reached).
|
||||
*
|
||||
* Note: read_key sets errno to 0 on success.
|
||||
|
@ -2197,14 +2198,16 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
|
|||
IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;)
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
/* It was EINTR. Repeat read_key() unless... */
|
||||
if (state->flags & LI_INTERRUPTIBLE) {
|
||||
/* LI_INTERRUPTIBLE bails out on EINTR,
|
||||
* but nothing really guarantees that bb_got_signal
|
||||
* is nonzero. Follow the least surprise principle:
|
||||
/* LI_INTERRUPTIBLE bails out on EINTR
|
||||
* if bb_got_signal became nonzero.
|
||||
* (It may stay zero: for example, our SIGWINCH
|
||||
* handler does not set it. This is used for signals
|
||||
* which should not interrupt line editing).
|
||||
*/
|
||||
if (bb_got_signal == 0)
|
||||
bb_got_signal = 255;
|
||||
goto ret;
|
||||
if (bb_got_signal != 0)
|
||||
goto ret; /* will return -1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10821,7 +10821,8 @@ preadfd(void)
|
|||
again:
|
||||
/* For shell, LI_INTERRUPTIBLE is set:
|
||||
* read_line_input will abort on either
|
||||
* getting EINTR in poll(), or if it sees bb_got_signal != 0
|
||||
* getting EINTR in poll() and bb_got_signal became != 0,
|
||||
* or if it sees bb_got_signal != 0
|
||||
* (IOW: if signal arrives before poll() is reached).
|
||||
* Interactive testcases:
|
||||
* (while kill -INT $$; do sleep 1; done) &
|
||||
|
|
10
shell/hush.c
10
shell/hush.c
|
@ -1946,7 +1946,12 @@ static void record_pending_signo(int sig)
|
|||
{
|
||||
sigaddset(&G.pending_set, sig);
|
||||
#if ENABLE_FEATURE_EDITING
|
||||
bb_got_signal = sig; /* for read_line_input: "we got a signal" */
|
||||
if (sig != SIGCHLD
|
||||
|| (G_traps && G_traps[SIGCHLD] && G_traps[SIGCHLD][0])
|
||||
/* ^^^ if SIGCHLD, interrupt line reading only if it has a trap */
|
||||
) {
|
||||
bb_got_signal = sig; /* for read_line_input: "we got a signal" */
|
||||
}
|
||||
#endif
|
||||
#if ENABLE_HUSH_FAST
|
||||
if (sig == SIGCHLD) {
|
||||
|
@ -2669,7 +2674,8 @@ static int get_user_input(struct in_str *i)
|
|||
} else {
|
||||
/* For shell, LI_INTERRUPTIBLE is set:
|
||||
* read_line_input will abort on either
|
||||
* getting EINTR in poll(), or if it sees bb_got_signal != 0
|
||||
* getting EINTR in poll() and bb_got_signal became != 0,
|
||||
* or if it sees bb_got_signal != 0
|
||||
* (IOW: if signal arrives before poll() is reached).
|
||||
* Interactive testcases:
|
||||
* (while kill -INT $$; do sleep 1; done) &
|
||||
|
|
Loading…
Reference in New Issue