diff options
| author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-21 13:42:52 +0000 |
|---|---|---|
| committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-21 13:42:52 +0000 |
| commit | fc3ae83cd4e9049adb47ebfbd80ce3931a186ab5 (patch) | |
| tree | 06b88f81bb62ecdc2850705c1845ba9a963cc09b | |
| parent | 8e9f2a1033ed906625ed0b795bf29f2506092397 (diff) | |
| download | busybox-w32-fc3ae83cd4e9049adb47ebfbd80ce3931a186ab5.tar.gz busybox-w32-fc3ae83cd4e9049adb47ebfbd80ce3931a186ab5.tar.bz2 busybox-w32-fc3ae83cd4e9049adb47ebfbd80ce3931a186ab5.zip | |
hush: fix more backgrounding bugs. Plenty of them remains still.
git-svn-id: svn://busybox.net/trunk/busybox@18508 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -rw-r--r-- | shell/README | 8 | ||||
| -rw-r--r-- | shell/hush.c | 32 |
2 files changed, 29 insertions, 11 deletions
diff --git a/shell/README b/shell/README index bcd84dcad..b78d651a5 100644 --- a/shell/README +++ b/shell/README | |||
| @@ -1,6 +1,12 @@ | |||
| 1 | Various bits of what is known about busybox shells, in no particular order. | 1 | Various bits of what is known about busybox shells, in no particular order. |
| 2 | 2 | ||
| 3 | 2007-04-22 | 3 | 2007-04-21 |
| 4 | hush: fixed non-backgrounding of "sleep 1 &" and totally broken | ||
| 5 | "sleep 1 | sleep 2 &". Noticed a bug where successive jobs | ||
| 6 | get numbers 1,2,3 even when job #1 has exited before job# 2 is started. | ||
| 7 | (bash reuses #1 in this case) | ||
| 8 | |||
| 9 | 2007-04-21 | ||
| 4 | hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted | 10 | hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted |
| 5 | _before_ pipe gets executed!! run_list_real() already has "pipe;echo" | 11 | _before_ pipe gets executed!! run_list_real() already has "pipe;echo" |
| 6 | parsed and handed to it for execution, so it sees "pipe"; "echo 0". | 12 | parsed and handed to it for execution, so it sees "pipe"; "echo 0". |
diff --git a/shell/hush.c b/shell/hush.c index db93f8dcb..046e098d9 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -384,6 +384,7 @@ static int parse_string_outer(const char *s, int flag); | |||
| 384 | static int parse_file_outer(FILE *f); | 384 | static int parse_file_outer(FILE *f); |
| 385 | /* job management: */ | 385 | /* job management: */ |
| 386 | static int checkjobs(struct pipe* fg_pipe); | 386 | static int checkjobs(struct pipe* fg_pipe); |
| 387 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe); | ||
| 387 | static void insert_bg_job(struct pipe *pi); | 388 | static void insert_bg_job(struct pipe *pi); |
| 388 | static void remove_bg_job(struct pipe *pi); | 389 | static void remove_bg_job(struct pipe *pi); |
| 389 | /* local variable support */ | 390 | /* local variable support */ |
| @@ -648,6 +649,8 @@ static int builtin_fg_bg(struct child_prog *child) | |||
| 648 | bb_error_msg("%s: %d: no such job", child->argv[0], jobnum); | 649 | bb_error_msg("%s: %d: no such job", child->argv[0], jobnum); |
| 649 | return EXIT_FAILURE; | 650 | return EXIT_FAILURE; |
| 650 | found: | 651 | found: |
| 652 | // TODO: bash prints a string representation | ||
| 653 | // of job being foregrounded (like "sleep 1 | cat") | ||
| 651 | if (*child->argv[0] == 'f') { | 654 | if (*child->argv[0] == 'f') { |
| 652 | /* Put the job into the foreground. */ | 655 | /* Put the job into the foreground. */ |
| 653 | tcsetpgrp(interactive_fd, pi->pgrp); | 656 | tcsetpgrp(interactive_fd, pi->pgrp); |
| @@ -658,6 +661,7 @@ static int builtin_fg_bg(struct child_prog *child) | |||
| 658 | pi->progs[i].is_stopped = 0; | 661 | pi->progs[i].is_stopped = 0; |
| 659 | 662 | ||
| 660 | i = kill(- pi->pgrp, SIGCONT); | 663 | i = kill(- pi->pgrp, SIGCONT); |
| 664 | pi->stopped_progs = 0; | ||
| 661 | if (i < 0) { | 665 | if (i < 0) { |
| 662 | if (errno == ESRCH) { | 666 | if (errno == ESRCH) { |
| 663 | remove_bg_job(pi); | 667 | remove_bg_job(pi); |
| @@ -666,7 +670,8 @@ static int builtin_fg_bg(struct child_prog *child) | |||
| 666 | } | 670 | } |
| 667 | } | 671 | } |
| 668 | 672 | ||
| 669 | pi->stopped_progs = 0; | 673 | if (*child->argv[0] == 'f') |
| 674 | return checkjobs_and_fg_shell(pi); | ||
| 670 | return EXIT_SUCCESS; | 675 | return EXIT_SUCCESS; |
| 671 | } | 676 | } |
| 672 | 677 | ||
| @@ -1350,6 +1355,18 @@ static int checkjobs(struct pipe* fg_pipe) | |||
| 1350 | return rcode; | 1355 | return rcode; |
| 1351 | } | 1356 | } |
| 1352 | 1357 | ||
| 1358 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | ||
| 1359 | { | ||
| 1360 | pid_t p; | ||
| 1361 | int rcode = checkjobs(fg_pipe); | ||
| 1362 | /* Job finished, move the shell to the foreground */ | ||
| 1363 | p = getpgid(0); | ||
| 1364 | debug_printf("fg'ing ourself: getpgid(0)=%d\n", (int)p); | ||
| 1365 | if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY) | ||
| 1366 | bb_perror_msg("tcsetpgrp-4a"); | ||
| 1367 | return rcode; | ||
| 1368 | } | ||
| 1369 | |||
| 1353 | /* run_pipe_real() starts all the jobs, but doesn't wait for anything | 1370 | /* run_pipe_real() starts all the jobs, but doesn't wait for anything |
| 1354 | * to finish. See checkjobs(). | 1371 | * to finish. See checkjobs(). |
| 1355 | * | 1372 | * |
| @@ -1377,6 +1394,7 @@ static int run_pipe_real(struct pipe *pi) | |||
| 1377 | /* it is not always needed, but we aim to smaller code */ | 1394 | /* it is not always needed, but we aim to smaller code */ |
| 1378 | int squirrel[] = { -1, -1, -1 }; | 1395 | int squirrel[] = { -1, -1, -1 }; |
| 1379 | int rcode; | 1396 | int rcode; |
| 1397 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); | ||
| 1380 | 1398 | ||
| 1381 | nextin = 0; | 1399 | nextin = 0; |
| 1382 | pi->pgrp = -1; | 1400 | pi->pgrp = -1; |
| @@ -1386,7 +1404,7 @@ static int run_pipe_real(struct pipe *pi) | |||
| 1386 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. | 1404 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. |
| 1387 | */ | 1405 | */ |
| 1388 | child = &(pi->progs[0]); | 1406 | child = &(pi->progs[0]); |
| 1389 | if (pi->num_progs == 1 && child->group && child->subshell == 0) { | 1407 | if (single_fg && child->group && child->subshell == 0) { |
| 1390 | debug_printf("non-subshell grouping\n"); | 1408 | debug_printf("non-subshell grouping\n"); |
| 1391 | setup_redirects(child, squirrel); | 1409 | setup_redirects(child, squirrel); |
| 1392 | /* XXX could we merge code with following builtin case, | 1410 | /* XXX could we merge code with following builtin case, |
| @@ -1396,7 +1414,7 @@ static int run_pipe_real(struct pipe *pi) | |||
| 1396 | return rcode; | 1414 | return rcode; |
| 1397 | } | 1415 | } |
| 1398 | 1416 | ||
| 1399 | if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { | 1417 | if (single_fg && pi->progs[0].argv != NULL) { |
| 1400 | for (i = 0; is_assignment(child->argv[i]); i++) | 1418 | for (i = 0; is_assignment(child->argv[i]); i++) |
| 1401 | continue; | 1419 | continue; |
| 1402 | if (i != 0 && child->argv[i] == NULL) { | 1420 | if (i != 0 && child->argv[i] == NULL) { |
| @@ -1675,13 +1693,7 @@ static int run_list_real(struct pipe *pi) | |||
| 1675 | rcode = EXIT_SUCCESS; | 1693 | rcode = EXIT_SUCCESS; |
| 1676 | } else { | 1694 | } else { |
| 1677 | if (interactive_fd) { | 1695 | if (interactive_fd) { |
| 1678 | pid_t p; | 1696 | rcode = checkjobs_and_fg_shell(pi); |
| 1679 | rcode = checkjobs(pi); | ||
| 1680 | /* move the shell to the foreground */ | ||
| 1681 | p = getpgid(0); | ||
| 1682 | if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY) | ||
| 1683 | bb_perror_msg("tcsetpgrp-4"); | ||
| 1684 | debug_printf("getpgid(0)=%d\n", (int)p); | ||
| 1685 | } else { | 1697 | } else { |
| 1686 | rcode = checkjobs(pi); | 1698 | rcode = checkjobs(pi); |
| 1687 | } | 1699 | } |
