aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-01-26 12:56:33 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2023-01-26 12:56:33 +0100
commit93e0898c663a533082b5f3c2e7dcce93ec47076d (patch)
treed44936a40fcac122b94d4b235195e6832446b27b
parentc2739e11dee92770839ac9b2dbf020459baec7b9 (diff)
downloadbusybox-w32-93e0898c663a533082b5f3c2e7dcce93ec47076d.tar.gz
busybox-w32-93e0898c663a533082b5f3c2e7dcce93ec47076d.tar.bz2
busybox-w32-93e0898c663a533082b5f3c2e7dcce93ec47076d.zip
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>
-rw-r--r--libbb/lineedit.c17
-rw-r--r--shell/ash.c3
-rw-r--r--shell/hush.c10
3 files changed, 20 insertions, 10 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index d6b2e76ff..b942f540a 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2180,7 +2180,8 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
2180 * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls". 2180 * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls".
2181 * 2181 *
2182 * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll() 2182 * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll()
2183 * inside read_key, or if bb_got_signal != 0 (IOW: if signal 2183 * inside read_key and bb_got_signal became != 0,
2184 * or if bb_got_signal != 0 (IOW: if signal
2184 * arrived before poll() is reached). 2185 * arrived before poll() is reached).
2185 * 2186 *
2186 * Note: read_key sets errno to 0 on success. 2187 * Note: read_key sets errno to 0 on success.
@@ -2197,14 +2198,16 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
2197 IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) 2198 IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;)
2198 if (errno != EINTR) 2199 if (errno != EINTR)
2199 break; 2200 break;
2201 /* It was EINTR. Repeat read_key() unless... */
2200 if (state->flags & LI_INTERRUPTIBLE) { 2202 if (state->flags & LI_INTERRUPTIBLE) {
2201 /* LI_INTERRUPTIBLE bails out on EINTR, 2203 /* LI_INTERRUPTIBLE bails out on EINTR
2202 * but nothing really guarantees that bb_got_signal 2204 * if bb_got_signal became nonzero.
2203 * is nonzero. Follow the least surprise principle: 2205 * (It may stay zero: for example, our SIGWINCH
2206 * handler does not set it. This is used for signals
2207 * which should not interrupt line editing).
2204 */ 2208 */
2205 if (bb_got_signal == 0) 2209 if (bb_got_signal != 0)
2206 bb_got_signal = 255; 2210 goto ret; /* will return -1 */
2207 goto ret;
2208 } 2211 }
2209 } 2212 }
2210 2213
diff --git a/shell/ash.c b/shell/ash.c
index 18ccc1329..5f8c8ea19 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10821,7 +10821,8 @@ preadfd(void)
10821 again: 10821 again:
10822 /* For shell, LI_INTERRUPTIBLE is set: 10822 /* For shell, LI_INTERRUPTIBLE is set:
10823 * read_line_input will abort on either 10823 * read_line_input will abort on either
10824 * getting EINTR in poll(), or if it sees bb_got_signal != 0 10824 * getting EINTR in poll() and bb_got_signal became != 0,
10825 * or if it sees bb_got_signal != 0
10825 * (IOW: if signal arrives before poll() is reached). 10826 * (IOW: if signal arrives before poll() is reached).
10826 * Interactive testcases: 10827 * Interactive testcases:
10827 * (while kill -INT $$; do sleep 1; done) & 10828 * (while kill -INT $$; do sleep 1; done) &
diff --git a/shell/hush.c b/shell/hush.c
index d111f0cc5..f064b8fd2 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1946,7 +1946,12 @@ static void record_pending_signo(int sig)
1946{ 1946{
1947 sigaddset(&G.pending_set, sig); 1947 sigaddset(&G.pending_set, sig);
1948#if ENABLE_FEATURE_EDITING 1948#if ENABLE_FEATURE_EDITING
1949 bb_got_signal = sig; /* for read_line_input: "we got a signal" */ 1949 if (sig != SIGCHLD
1950 || (G_traps && G_traps[SIGCHLD] && G_traps[SIGCHLD][0])
1951 /* ^^^ if SIGCHLD, interrupt line reading only if it has a trap */
1952 ) {
1953 bb_got_signal = sig; /* for read_line_input: "we got a signal" */
1954 }
1950#endif 1955#endif
1951#if ENABLE_HUSH_FAST 1956#if ENABLE_HUSH_FAST
1952 if (sig == SIGCHLD) { 1957 if (sig == SIGCHLD) {
@@ -2669,7 +2674,8 @@ static int get_user_input(struct in_str *i)
2669 } else { 2674 } else {
2670 /* For shell, LI_INTERRUPTIBLE is set: 2675 /* For shell, LI_INTERRUPTIBLE is set:
2671 * read_line_input will abort on either 2676 * read_line_input will abort on either
2672 * getting EINTR in poll(), or if it sees bb_got_signal != 0 2677 * getting EINTR in poll() and bb_got_signal became != 0,
2678 * or if it sees bb_got_signal != 0
2673 * (IOW: if signal arrives before poll() is reached). 2679 * (IOW: if signal arrives before poll() is reached).
2674 * Interactive testcases: 2680 * Interactive testcases:
2675 * (while kill -INT $$; do sleep 1; done) & 2681 * (while kill -INT $$; do sleep 1; done) &