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?
|
char buf[MAXLINE]; // command will be parsed and modified?
|
||||||
int bg; // whether it runs in background
|
int bg; // whether it runs in background
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
sigset_t mask;
|
||||||
|
sigemptyset(&mask);
|
||||||
// preprocess cmd line
|
// preprocess cmd line
|
||||||
strcpy(buf, cmdline);
|
strcpy(buf, cmdline);
|
||||||
bg = parseline(buf, argv); // convert the command into argv
|
bg = parseline(buf, argv); // convert the command into argv
|
||||||
|
@ -179,26 +181,29 @@ void eval(char *cmdline)
|
||||||
// run external command
|
// run external command
|
||||||
if (!builtin_cmd(argv)) // built-in command is done in `builtin_cmd`
|
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
|
if (execve(argv[0], argv, environ) < 0) // execute command failed
|
||||||
{
|
{
|
||||||
printf("%s: Command not found\n", argv[0]);
|
printf("%s: Command not found\n", argv[0]);
|
||||||
exit(0); // here only child exited
|
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
|
// wait for foreground job to terminate
|
||||||
{
|
{
|
||||||
int status;
|
waitfg(pid); // the waiting stuff should be done in `waitfg`
|
||||||
if (waitpid(pid, &status, 0) < 0) // if return -1, then waiting failed
|
|
||||||
{
|
|
||||||
unix_error("waitfg: waitpid error");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("%d %s", pid, cmdline);
|
printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline); // background job information
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -271,6 +276,11 @@ int builtin_cmd(char **argv)
|
||||||
{
|
{
|
||||||
exit(0);
|
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 */
|
return 0; /* not a builtin command */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +297,10 @@ void do_bgfg(char **argv)
|
||||||
*/
|
*/
|
||||||
void waitfg(pid_t pid)
|
void waitfg(pid_t pid)
|
||||||
{
|
{
|
||||||
|
while (pid == fgpid(jobs))
|
||||||
|
{
|
||||||
|
sleep(0);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +317,15 @@ void waitfg(pid_t pid)
|
||||||
*/
|
*/
|
||||||
void sigchld_handler(int sig)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue