aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c7
-rw-r--r--shell/ash_test/ash-read/read_SIGCHLD.right2
-rwxr-xr-xshell/ash_test/ash-read/read_SIGCHLD.tests4
-rw-r--r--shell/hush.c5
-rw-r--r--shell/hush_test/hush-read/read_SIGCHLD.right2
-rwxr-xr-xshell/hush_test/hush-read/read_SIGCHLD.tests4
-rw-r--r--shell/shell_common.c20
7 files changed, 34 insertions, 10 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 70ee15ed8..60c8ffeb7 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -13268,6 +13268,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13268 /* "read -s" needs to save/restore termios, can't allow ^C 13268 /* "read -s" needs to save/restore termios, can't allow ^C
13269 * to jump out of it. 13269 * to jump out of it.
13270 */ 13270 */
13271 again:
13271 INT_OFF; 13272 INT_OFF;
13272 r = shell_builtin_read(setvar0, 13273 r = shell_builtin_read(setvar0,
13273 argptr, 13274 argptr,
@@ -13280,6 +13281,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13280 ); 13281 );
13281 INT_ON; 13282 INT_ON;
13282 13283
13284 if ((uintptr_t)r == 1 && errno == EINTR) {
13285 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13286 if (pending_sig == 0)
13287 goto again;
13288 }
13289
13283 if ((uintptr_t)r > 1) 13290 if ((uintptr_t)r > 1)
13284 ash_msg_and_raise_error(r); 13291 ash_msg_and_raise_error(r);
13285 13292
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.right b/shell/ash_test/ash-read/read_SIGCHLD.right
new file mode 100644
index 000000000..b3dc7ab0c
--- /dev/null
+++ b/shell/ash_test/ash-read/read_SIGCHLD.right
@@ -0,0 +1,2 @@
1x='Ok'
2exitcode:0
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.tests b/shell/ash_test/ash-read/read_SIGCHLD.tests
new file mode 100755
index 000000000..c5f673aff
--- /dev/null
+++ b/shell/ash_test/ash-read/read_SIGCHLD.tests
@@ -0,0 +1,4 @@
1x=BAD
2{ sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; }
3echo "exitcode:$?"
4
diff --git a/shell/hush.c b/shell/hush.c
index e18920f50..125463a56 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9038,6 +9038,9 @@ static int FAST_FUNC builtin_type(char **argv)
9038 * - terminates shell (regardless of interactivity); 9038 * - terminates shell (regardless of interactivity);
9039 * if it has non-empty trap: 9039 * if it has non-empty trap:
9040 * - executes trap and returns to read; 9040 * - executes trap and returns to read;
9041 * SIGCHLD from children:
9042 * - does not interrupt read regardless of interactivity:
9043 * try: sleep 1 & read x; echo $x
9041 */ 9044 */
9042static int FAST_FUNC builtin_read(char **argv) 9045static int FAST_FUNC builtin_read(char **argv)
9043{ 9046{
@@ -9071,7 +9074,7 @@ static int FAST_FUNC builtin_read(char **argv)
9071 9074
9072 if ((uintptr_t)r == 1 && errno == EINTR) { 9075 if ((uintptr_t)r == 1 && errno == EINTR) {
9073 unsigned sig = check_and_run_traps(); 9076 unsigned sig = check_and_run_traps();
9074 if (sig && sig != SIGINT) 9077 if (sig != SIGINT)
9075 goto again; 9078 goto again;
9076 } 9079 }
9077 9080
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.right b/shell/hush_test/hush-read/read_SIGCHLD.right
new file mode 100644
index 000000000..b3dc7ab0c
--- /dev/null
+++ b/shell/hush_test/hush-read/read_SIGCHLD.right
@@ -0,0 +1,2 @@
1x='Ok'
2exitcode:0
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.tests b/shell/hush_test/hush-read/read_SIGCHLD.tests
new file mode 100755
index 000000000..c5f673aff
--- /dev/null
+++ b/shell/hush_test/hush-read/read_SIGCHLD.tests
@@ -0,0 +1,4 @@
1x=BAD
2{ sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; }
3echo "exitcode:$?"
4
diff --git a/shell/shell_common.c b/shell/shell_common.c
index fb86e680f..03b7d0b75 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -204,15 +204,17 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
204 c = buffer[bufpos]; 204 c = buffer[bufpos];
205 if (c == '\0') 205 if (c == '\0')
206 continue; 206 continue;
207 if (backslash) { 207 if (!(read_flags & BUILTIN_READ_RAW)) {
208 backslash = 0; 208 if (backslash) {
209 if (c != '\n') 209 backslash = 0;
210 goto put; 210 if (c != '\n')
211 continue; 211 goto put;
212 } 212 continue;
213 if (!(read_flags & BUILTIN_READ_RAW) && c == '\\') { 213 }
214 backslash = 1; 214 if (c == '\\') {
215 continue; 215 backslash = 1;
216 continue;
217 }
216 } 218 }
217 if (c == '\n') 219 if (c == '\n')
218 break; 220 break;