/******************************* * Wrappers for the SIO routines ******************************/ ssize_t Sio_putl(long v) { ssize_t n; if ((n = sio_putl(v)) < 0) sio_error("Sio_putl error"); return n; }
/* * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever * a child job terminates (becomes a zombie), or stops because it * received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The * handler reaps all available zombie children, but doesn't wait * for any other currently running children to terminate. */ void sigchld_handler(int sig) { int status; pid_t pid; int olderrno = errno; // store errno in handler /* * Reap child with the pid if the child is stopped or terminated * If a child is terminated normally, delete the child from the job list * If a child is stopped by a signal, set the job status as stopped * If a child is terminated by a signal that was not caught, delete the child from the job list */ while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) { if (WIFEXITED(status)) { deletejob(job_list, pid); // the child ternimated normally } else if (WIFSTOPPED(status)) { /* * Avoid printf() in handler, use helper function to write the output to stdout */ sio_puts("Job ["); sio_putl(pid2jid(pid)); sio_puts("] ("); sio_putl(pid); sio_puts(") stopped by signal "); sio_putl(WSTOPSIG(status)); sio_puts("\n"); getjobpid(job_list, pid) -> state = ST; // the child was stopped by a signal } else if (WIFSIGNALED(status)) { // the child was terminated by a signal that was not caught /* * Avoid printf() in handler, use helper function to write the output to stdout */ sio_puts("Job ["); sio_putl(pid2jid(pid)); sio_puts("] ("); sio_putl(pid); sio_puts(") terminated by signal "); sio_putl(WTERMSIG(status)); sio_puts("\n"); deletejob(job_list, pid); } } errno = olderrno; return; }