Shell Lab: trace05

This commit is contained in:
cyp0633 2022-05-25 10:24:23 +08:00
parent dd323368d0
commit adb69ffca0
Signed by: cyp0633
GPG Key ID: E1BC508A994A5138
1 changed files with 31 additions and 8 deletions

View File

@ -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;
}