ash,hush: fix SIGCHLD interrupting read builtin
No binary (build failed)
—
(log yok)
| @@ -13268,6 +13268,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |
| /* "read -s" needs to save/restore termios, can't allow ^C | |
| * to jump out of it. | |
| */ | |
| + | again: |
| INT_OFF; | |
| r = shell_builtin_read(setvar0, | |
| argptr, | |
| @@ -13280,6 +13281,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |
| ); | |
| INT_ON; | |
| + | if ((uintptr_t)r == 1 && errno == EINTR) { |
| + | /* to get SIGCHLD: sleep 1 & read x; echo $x */ |
| + | if (pending_sig == 0) |
| + | goto again; |
| + | } |
| + | |
| if ((uintptr_t)r > 1) | |
| ash_msg_and_raise_error(r); | |
| @@ -0,0 +1,2 @@ | |
| + | x='Ok' |
| + | exitcode:0 |
| @@ -0,0 +1,4 @@ | |
| + | x=BAD |
| + | { sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; } |
| + | echo "exitcode:$?" |
| + | |
| @@ -9038,6 +9038,9 @@ static int FAST_FUNC builtin_type(char **argv) | |
| * - terminates shell (regardless of interactivity); | |
| * if it has non-empty trap: | |
| * - executes trap and returns to read; | |
| + | * SIGCHLD from children: |
| + | * - does not interrupt read regardless of interactivity: |
| + | * try: sleep 1 & read x; echo $x |
| */ | |
| static int FAST_FUNC builtin_read(char **argv) | |
| { | |
| @@ -9071,7 +9074,7 @@ static int FAST_FUNC builtin_read(char **argv) | |
| if ((uintptr_t)r == 1 && errno == EINTR) { | |
| unsigned sig = check_and_run_traps(); | |
| - | if (sig && sig != SIGINT) |
| + | if (sig != SIGINT) |
| goto again; | |
| } | |
| @@ -0,0 +1,2 @@ | |
| + | x='Ok' |
| + | exitcode:0 |
| @@ -0,0 +1,4 @@ | |
| + | x=BAD |
| + | { sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; } |
| + | echo "exitcode:$?" |
| + | |
| @@ -204,15 +204,17 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |
| c = buffer[bufpos]; | |
| if (c == '\0') | |
| continue; | |
| - | if (backslash) { |
| - | backslash = 0; |
| - | if (c != '\n') |
| - | goto put; |
| - | continue; |
| - | } |
| - | if (!(read_flags & BUILTIN_READ_RAW) && c == '\\') { |
| - | backslash = 1; |
| - | continue; |
| + | if (!(read_flags & BUILTIN_READ_RAW)) { |
| + | if (backslash) { |
| + | backslash = 0; |
| + | if (c != '\n') |
| + | goto put; |
| + | continue; |
| + | } |
| + | if (c == '\\') { |
| + | backslash = 1; |
| + | continue; |
| + | } |
| } | |
| if (c == '\n') | |
| break; | |