diff options
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 e14c787..f76afd3 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2161,12 +2161,30 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) * insist on full MB_CUR_MAX buffer to declare input like * "\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 + * arrived before poll() is reached). + * * Note: read_key sets errno to 0 on success. */ - IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) - ic = read_key(STDIN_FILENO, read_key_buffer, timeout); - IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) + do { + if ((state->flags & LI_INTERRUPTIBLE) && bb_got_signal) { + errno = EINTR; + return -1; + } +//FIXME: still races here with signals, but small window to poll() inside read_key + IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) + ic = read_key(STDIN_FILENO, read_key_buffer, timeout); + IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) + } while (!(state->flags & LI_INTERRUPTIBLE) && errno == EINTR); + if (errno) { + /* LI_INTERRUPTIBLE can bail out with EINTR here, + * but nothing really guarantees that bb_got_signal + * is nonzero. Follow the least surprise principle: + */ + if (errno == EINTR && bb_got_signal == 0) + bb_got_signal = 255; /* something nonzero */ #if ENABLE_UNICODE_SUPPORT if (errno == EAGAIN && unicode_idx != 0) goto pushback; diff --git a/libbb/read_key.c b/libbb/read_key.c index 03b7da6..829ae21 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) * if fd can be in non-blocking mode. */ if (timeout >= -1) { - if (safe_poll(&pfd, 1, timeout) == 0) { + n = poll(&pfd, 1, timeout); + if (n < 0 && errno == EINTR) + return n; + if (n == 0) { /* Timed out */ errno = EAGAIN; return -1; @@ -138,7 +141,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) * When we were reading 3 bytes here, we were eating * "li" too, and cat was getting wrong input. */ - n = safe_read(fd, buffer, 1); + n = read(fd, buffer, 1); if (n <= 0) return -1; } @@ -284,6 +287,15 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) goto start_over; } +int64_t FAST_FUNC safe_read_key(int fd, char *buffer, int timeout) +{ + int64_t r; + do { + r = read_key(fd, buffer, timeout); + } while (errno == EINTR); + return r; +} + void FAST_FUNC read_key_ungets(char *buffer, const char *str, unsigned len) { unsigned cur_len = (unsigned char)buffer[0]; |