diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/shell/ash.c b/shell/ash.c index 086773dd7..55df54bd0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3679,7 +3679,9 @@ signal_handler(int signo) | |||
3679 | if (!trap[SIGCHLD]) | 3679 | if (!trap[SIGCHLD]) |
3680 | return; | 3680 | return; |
3681 | } | 3681 | } |
3682 | 3682 | #if ENABLE_FEATURE_EDITING | |
3683 | bb_got_signal = signo; /* for read_line_input: "we got a signal" */ | ||
3684 | #endif | ||
3683 | gotsig[signo - 1] = 1; | 3685 | gotsig[signo - 1] = 1; |
3684 | pending_sig = signo; | 3686 | pending_sig = signo; |
3685 | 3687 | ||
@@ -10784,33 +10786,52 @@ preadfd(void) | |||
10784 | # endif | 10786 | # endif |
10785 | reinit_unicode_for_ash(); | 10787 | reinit_unicode_for_ash(); |
10786 | again: | 10788 | again: |
10787 | //BUG: not in INT_OFF/INT_ON section - SIGINT et al would longjmp out of read_line_input()! | 10789 | /* For shell, LI_INTERRUPTIBLE is set: |
10788 | //This would cause a memory leak in interactive shell | 10790 | * read_line_input will abort on either |
10789 | //(repeated internal allocations in read_line_input): | 10791 | * getting EINTR in poll(), or if it sees bb_got_signal != 0 |
10790 | // (while kill -INT $$; do :; done) & | 10792 | * (IOW: if signal arrives before poll() is reached). |
10793 | * Interactive testcases: | ||
10794 | * (while kill -INT $$; do sleep 1; done) & | ||
10795 | * #^^^ prints ^C, prints prompt, repeats | ||
10796 | * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) & | ||
10797 | * #^^^ prints ^C, prints "I", prints prompt, repeats | ||
10798 | * trap 'echo T' term; (while kill $$; do sleep 1; done) & | ||
10799 | * #^^^ prints "T", prints prompt, repeats | ||
10800 | * #(bash 5.0.17 exits after first "T", looks like a bug) | ||
10801 | */ | ||
10802 | bb_got_signal = 0; | ||
10803 | INT_OFF; /* no longjmp'ing out of read_line_input please */ | ||
10791 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ); | 10804 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ); |
10805 | if (bb_got_signal == SIGINT) | ||
10806 | write(STDOUT_FILENO, "^C\n", 3); | ||
10807 | INT_ON; /* here non-blocked SIGINT will longjmp */ | ||
10792 | if (nr == 0) { | 10808 | if (nr == 0) { |
10793 | /* ^C pressed, "convert" to SIGINT */ | 10809 | /* ^C pressed, "convert" to SIGINT */ |
10794 | write(STDOUT_FILENO, "^C", 2); | 10810 | write(STDOUT_FILENO, "^C\n", 3); |
10795 | raise(SIGINT); | 10811 | raise(SIGINT); /* here non-blocked SIGINT will longjmp */ |
10796 | /* raise(SIGINT) did not work! (e.g. if SIGINT | 10812 | /* raise(SIGINT) did not work! (e.g. if SIGINT |
10797 | * is SIG_IGNed on startup, it stays SIG_IGNed) | 10813 | * is SIG_IGNed on startup, it stays SIG_IGNed) |
10798 | */ | 10814 | */ |
10799 | if (trap[SIGINT]) { | 10815 | if (trap[SIGINT]) { |
10816 | empty_line_input: | ||
10800 | buf[0] = '\n'; | 10817 | buf[0] = '\n'; |
10801 | buf[1] = '\0'; | 10818 | buf[1] = '\0'; |
10802 | return 1; | 10819 | return 1; |
10803 | } | 10820 | } |
10804 | exitstatus = 128 + SIGINT; | 10821 | exitstatus = 128 + SIGINT; |
10805 | /* bash behavior on ^C + ignored SIGINT: */ | 10822 | /* bash behavior on ^C + ignored SIGINT: */ |
10806 | write(STDOUT_FILENO, "\n", 1); | ||
10807 | goto again; | 10823 | goto again; |
10808 | } | 10824 | } |
10809 | if (nr < 0) { | 10825 | if (nr < 0) { |
10810 | if (errno == 0) { | 10826 | if (errno == 0) { |
10811 | /* Ctrl+D pressed */ | 10827 | /* ^D pressed */ |
10812 | nr = 0; | 10828 | nr = 0; |
10813 | } | 10829 | } |
10830 | else if (errno == EINTR) { /* got signal? */ | ||
10831 | if (bb_got_signal != SIGINT) | ||
10832 | write(STDOUT_FILENO, "\n", 1); | ||
10833 | goto empty_line_input; | ||
10834 | } | ||
10814 | # if ENABLE_ASH_IDLE_TIMEOUT | 10835 | # if ENABLE_ASH_IDLE_TIMEOUT |
10815 | else if (errno == EAGAIN && timeout > 0) { | 10836 | else if (errno == EAGAIN && timeout > 0) { |
10816 | puts("\007timed out waiting for input: auto-logout"); | 10837 | puts("\007timed out waiting for input: auto-logout"); |