Shell Lab: trace05
This commit is contained in:
parent
dd323368d0
commit
adb69ffca0
39
shlab/tsh.c
39
shlab/tsh.c
|
@ -169,6 +169,8 @@ void eval(char *cmdline)
|
|||
char buf[MAXLINE]; // command will be parsed and modified?
|
||||
int bg; // whether it runs in background
|
||||
pid_t pid;
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
// preprocess cmd line
|
||||
strcpy(buf, cmdline);
|
||||
bg = parseline(buf, argv); // convert the command into argv
|
||||
|
@ -179,26 +181,29 @@ void eval(char *cmdline)
|
|||
// run external command
|
||||
if (!builtin_cmd(argv)) // built-in command is done in `builtin_cmd`
|
||||
{
|
||||
if ((pid = fork()) == 0) // this is child
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL); // 5. block SIGCHLD
|
||||
if ((pid = fork()) == 0) // this is child
|
||||
{
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL); // 5. unblock SIGCHLD
|
||||
setpgid(0, 0); // put the child process (0=current) into a new process group (0=current)
|
||||
if (execve(argv[0], argv, environ) < 0) // execute command failed
|
||||
{
|
||||
printf("%s: Command not found\n", argv[0]);
|
||||
exit(0); // here only child exited
|
||||
}
|
||||
}
|
||||
if (!bg) // run the process in foreground:
|
||||
addjob(jobs, pid, bg ? BG : FG, cmdline); // add the job to job list.
|
||||
// When bg=1, state=2; bg=0, state=1. this way it's just elegant
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL); // 5. unblock SIGCHLD
|
||||
if (!bg) // run the process in foreground:
|
||||
// wait for foreground job to terminate
|
||||
{
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0) // if return -1, then waiting failed
|
||||
{
|
||||
unix_error("waitfg: waitpid error");
|
||||
}
|
||||
waitfg(pid); // the waiting stuff should be done in `waitfg`
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%d %s", pid, cmdline);
|
||||
printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline); // background job information
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -271,6 +276,11 @@ int builtin_cmd(char **argv)
|
|||
{
|
||||
exit(0);
|
||||
}
|
||||
if (strcmp(argv[0], "jobs") == 0) // t5: process jobs command
|
||||
{
|
||||
listjobs(jobs);
|
||||
return 1; // this IS a builtin command, return 1 to notify
|
||||
}
|
||||
return 0; /* not a builtin command */
|
||||
}
|
||||
|
||||
|
@ -287,6 +297,10 @@ void do_bgfg(char **argv)
|
|||
*/
|
||||
void waitfg(pid_t pid)
|
||||
{
|
||||
while (pid == fgpid(jobs))
|
||||
{
|
||||
sleep(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -303,6 +317,15 @@ void waitfg(pid_t pid)
|
|||
*/
|
||||
void sigchld_handler(int sig)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0) // check if a child has become zombie, without wait
|
||||
{
|
||||
if(WIFEXITED(status))
|
||||
{
|
||||
deletejob(jobs,pid); // remove pid from job list
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue