mirror of https://github.com/mirror/busybox.git
hush: fix more backgrounding bugs. Plenty of them remains still.
parent
2f1bb36a55
commit
52881e9f23
|
@ -1,6 +1,12 @@
|
||||||
Various bits of what is known about busybox shells, in no particular order.
|
Various bits of what is known about busybox shells, in no particular order.
|
||||||
|
|
||||||
2007-04-22
|
2007-04-21
|
||||||
|
hush: fixed non-backgrounding of "sleep 1 &" and totally broken
|
||||||
|
"sleep 1 | sleep 2 &". Noticed a bug where successive jobs
|
||||||
|
get numbers 1,2,3 even when job #1 has exited before job# 2 is started.
|
||||||
|
(bash reuses #1 in this case)
|
||||||
|
|
||||||
|
2007-04-21
|
||||||
hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted
|
hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted
|
||||||
_before_ pipe gets executed!! run_list_real() already has "pipe;echo"
|
_before_ pipe gets executed!! run_list_real() already has "pipe;echo"
|
||||||
parsed and handed to it for execution, so it sees "pipe"; "echo 0".
|
parsed and handed to it for execution, so it sees "pipe"; "echo 0".
|
||||||
|
|
32
shell/hush.c
32
shell/hush.c
|
@ -384,6 +384,7 @@ static int parse_string_outer(const char *s, int flag);
|
||||||
static int parse_file_outer(FILE *f);
|
static int parse_file_outer(FILE *f);
|
||||||
/* job management: */
|
/* job management: */
|
||||||
static int checkjobs(struct pipe* fg_pipe);
|
static int checkjobs(struct pipe* fg_pipe);
|
||||||
|
static int checkjobs_and_fg_shell(struct pipe* fg_pipe);
|
||||||
static void insert_bg_job(struct pipe *pi);
|
static void insert_bg_job(struct pipe *pi);
|
||||||
static void remove_bg_job(struct pipe *pi);
|
static void remove_bg_job(struct pipe *pi);
|
||||||
/* local variable support */
|
/* local variable support */
|
||||||
|
@ -648,6 +649,8 @@ static int builtin_fg_bg(struct child_prog *child)
|
||||||
bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
|
bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
found:
|
found:
|
||||||
|
// TODO: bash prints a string representation
|
||||||
|
// of job being foregrounded (like "sleep 1 | cat")
|
||||||
if (*child->argv[0] == 'f') {
|
if (*child->argv[0] == 'f') {
|
||||||
/* Put the job into the foreground. */
|
/* Put the job into the foreground. */
|
||||||
tcsetpgrp(interactive_fd, pi->pgrp);
|
tcsetpgrp(interactive_fd, pi->pgrp);
|
||||||
|
@ -658,6 +661,7 @@ static int builtin_fg_bg(struct child_prog *child)
|
||||||
pi->progs[i].is_stopped = 0;
|
pi->progs[i].is_stopped = 0;
|
||||||
|
|
||||||
i = kill(- pi->pgrp, SIGCONT);
|
i = kill(- pi->pgrp, SIGCONT);
|
||||||
|
pi->stopped_progs = 0;
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
if (errno == ESRCH) {
|
if (errno == ESRCH) {
|
||||||
remove_bg_job(pi);
|
remove_bg_job(pi);
|
||||||
|
@ -666,7 +670,8 @@ static int builtin_fg_bg(struct child_prog *child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pi->stopped_progs = 0;
|
if (*child->argv[0] == 'f')
|
||||||
|
return checkjobs_and_fg_shell(pi);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,6 +1355,18 @@ static int checkjobs(struct pipe* fg_pipe)
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
|
||||||
|
{
|
||||||
|
pid_t p;
|
||||||
|
int rcode = checkjobs(fg_pipe);
|
||||||
|
/* Job finished, move the shell to the foreground */
|
||||||
|
p = getpgid(0);
|
||||||
|
debug_printf("fg'ing ourself: getpgid(0)=%d\n", (int)p);
|
||||||
|
if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY)
|
||||||
|
bb_perror_msg("tcsetpgrp-4a");
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
/* run_pipe_real() starts all the jobs, but doesn't wait for anything
|
/* run_pipe_real() starts all the jobs, but doesn't wait for anything
|
||||||
* to finish. See checkjobs().
|
* to finish. See checkjobs().
|
||||||
*
|
*
|
||||||
|
@ -1377,6 +1394,7 @@ static int run_pipe_real(struct pipe *pi)
|
||||||
/* it is not always needed, but we aim to smaller code */
|
/* it is not always needed, but we aim to smaller code */
|
||||||
int squirrel[] = { -1, -1, -1 };
|
int squirrel[] = { -1, -1, -1 };
|
||||||
int rcode;
|
int rcode;
|
||||||
|
const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG);
|
||||||
|
|
||||||
nextin = 0;
|
nextin = 0;
|
||||||
pi->pgrp = -1;
|
pi->pgrp = -1;
|
||||||
|
@ -1386,7 +1404,7 @@ static int run_pipe_real(struct pipe *pi)
|
||||||
* pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
|
* pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
|
||||||
*/
|
*/
|
||||||
child = &(pi->progs[0]);
|
child = &(pi->progs[0]);
|
||||||
if (pi->num_progs == 1 && child->group && child->subshell == 0) {
|
if (single_fg && child->group && child->subshell == 0) {
|
||||||
debug_printf("non-subshell grouping\n");
|
debug_printf("non-subshell grouping\n");
|
||||||
setup_redirects(child, squirrel);
|
setup_redirects(child, squirrel);
|
||||||
/* XXX could we merge code with following builtin case,
|
/* XXX could we merge code with following builtin case,
|
||||||
|
@ -1396,7 +1414,7 @@ static int run_pipe_real(struct pipe *pi)
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
|
if (single_fg && pi->progs[0].argv != NULL) {
|
||||||
for (i = 0; is_assignment(child->argv[i]); i++)
|
for (i = 0; is_assignment(child->argv[i]); i++)
|
||||||
continue;
|
continue;
|
||||||
if (i != 0 && child->argv[i] == NULL) {
|
if (i != 0 && child->argv[i] == NULL) {
|
||||||
|
@ -1675,13 +1693,7 @@ static int run_list_real(struct pipe *pi)
|
||||||
rcode = EXIT_SUCCESS;
|
rcode = EXIT_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
if (interactive_fd) {
|
if (interactive_fd) {
|
||||||
pid_t p;
|
rcode = checkjobs_and_fg_shell(pi);
|
||||||
rcode = checkjobs(pi);
|
|
||||||
/* move the shell to the foreground */
|
|
||||||
p = getpgid(0);
|
|
||||||
if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY)
|
|
||||||
bb_perror_msg("tcsetpgrp-4");
|
|
||||||
debug_printf("getpgid(0)=%d\n", (int)p);
|
|
||||||
} else {
|
} else {
|
||||||
rcode = checkjobs(pi);
|
rcode = checkjobs(pi);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue