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