diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2022-01-17 03:02:40 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2022-01-17 11:46:23 +0100 |
commit | 12566e7f9b5e5c5d445bc4d36991d134b431dc6c (patch) | |
tree | 2571356a77f7d421da368e9b31dad182e83b2408 /libbb | |
parent | a277506a64404e6c4472ff89c944c4f353db1c33 (diff) | |
download | busybox-w32-12566e7f9b5e5c5d445bc4d36991d134b431dc6c.tar.gz busybox-w32-12566e7f9b5e5c5d445bc4d36991d134b431dc6c.tar.bz2 busybox-w32-12566e7f9b5e5c5d445bc4d36991d134b431dc6c.zip |
ash,hush: fix handling of SIGINT while waiting for interactive input
function old new delta
lineedit_read_key 160 237 +77
__pgetc 522 589 +67
fgetc_interactive 244 309 +65
safe_read_key - 39 +39
read_key 588 607 +19
record_pending_signo 23 32 +9
signal_handler 75 81 +6
.rodata 104312 104309 -3
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 6/1 up/down: 282/-3) Total: 279 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/lineedit.c | 24 | ||||
-rw-r--r-- | libbb/read_key.c | 16 |
2 files changed, 35 insertions, 5 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index e14c78707..f76afd37d 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -2161,12 +2161,30 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) | |||
2161 | * insist on full MB_CUR_MAX buffer to declare input like | 2161 | * insist on full MB_CUR_MAX buffer to declare input like |
2162 | * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls". | 2162 | * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls". |
2163 | * | 2163 | * |
2164 | * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll() | ||
2165 | * inside read_key, or if bb_got_signal != 0 (IOW: if signal | ||
2166 | * arrived before poll() is reached). | ||
2167 | * | ||
2164 | * Note: read_key sets errno to 0 on success. | 2168 | * Note: read_key sets errno to 0 on success. |
2165 | */ | 2169 | */ |
2166 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) | 2170 | do { |
2167 | ic = read_key(STDIN_FILENO, read_key_buffer, timeout); | 2171 | if ((state->flags & LI_INTERRUPTIBLE) && bb_got_signal) { |
2168 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) | 2172 | errno = EINTR; |
2173 | return -1; | ||
2174 | } | ||
2175 | //FIXME: still races here with signals, but small window to poll() inside read_key | ||
2176 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) | ||
2177 | ic = read_key(STDIN_FILENO, read_key_buffer, timeout); | ||
2178 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) | ||
2179 | } while (!(state->flags & LI_INTERRUPTIBLE) && errno == EINTR); | ||
2180 | |||
2169 | if (errno) { | 2181 | if (errno) { |
2182 | /* LI_INTERRUPTIBLE can bail out with EINTR here, | ||
2183 | * but nothing really guarantees that bb_got_signal | ||
2184 | * is nonzero. Follow the least surprise principle: | ||
2185 | */ | ||
2186 | if (errno == EINTR && bb_got_signal == 0) | ||
2187 | bb_got_signal = 255; /* something nonzero */ | ||
2170 | #if ENABLE_UNICODE_SUPPORT | 2188 | #if ENABLE_UNICODE_SUPPORT |
2171 | if (errno == EAGAIN && unicode_idx != 0) | 2189 | if (errno == EAGAIN && unicode_idx != 0) |
2172 | goto pushback; | 2190 | goto pushback; |
diff --git a/libbb/read_key.c b/libbb/read_key.c index 03b7da656..829ae215c 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c | |||
@@ -126,7 +126,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
126 | * if fd can be in non-blocking mode. | 126 | * if fd can be in non-blocking mode. |
127 | */ | 127 | */ |
128 | if (timeout >= -1) { | 128 | if (timeout >= -1) { |
129 | if (safe_poll(&pfd, 1, timeout) == 0) { | 129 | n = poll(&pfd, 1, timeout); |
130 | if (n < 0 && errno == EINTR) | ||
131 | return n; | ||
132 | if (n == 0) { | ||
130 | /* Timed out */ | 133 | /* Timed out */ |
131 | errno = EAGAIN; | 134 | errno = EAGAIN; |
132 | return -1; | 135 | return -1; |
@@ -138,7 +141,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
138 | * When we were reading 3 bytes here, we were eating | 141 | * When we were reading 3 bytes here, we were eating |
139 | * "li" too, and cat was getting wrong input. | 142 | * "li" too, and cat was getting wrong input. |
140 | */ | 143 | */ |
141 | n = safe_read(fd, buffer, 1); | 144 | n = read(fd, buffer, 1); |
142 | if (n <= 0) | 145 | if (n <= 0) |
143 | return -1; | 146 | return -1; |
144 | } | 147 | } |
@@ -284,6 +287,15 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
284 | goto start_over; | 287 | goto start_over; |
285 | } | 288 | } |
286 | 289 | ||
290 | int64_t FAST_FUNC safe_read_key(int fd, char *buffer, int timeout) | ||
291 | { | ||
292 | int64_t r; | ||
293 | do { | ||
294 | r = read_key(fd, buffer, timeout); | ||
295 | } while (errno == EINTR); | ||
296 | return r; | ||
297 | } | ||
298 | |||
287 | void FAST_FUNC read_key_ungets(char *buffer, const char *str, unsigned len) | 299 | void FAST_FUNC read_key_ungets(char *buffer, const char *str, unsigned len) |
288 | { | 300 | { |
289 | unsigned cur_len = (unsigned char)buffer[0]; | 301 | unsigned cur_len = (unsigned char)buffer[0]; |