ast_comparator/test/student_data/handout/shlab-handout/cases/63_tsh.c
/*
 * 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 or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.
 */
The kernel sends a SIGCHLD to the shell whenever
a child job terminates (becomes a zombie), or stops because it
received a SIGSTOP or SIGTSTP signal. The handler reaps all
available zombie children, but doesn't wait for any other
currently running children to terminate.
The kernel sends a SIGCHLD to the shell whenever a child job terminates ( becomes a zombie ) or stops because it received a SIGSTOP or SIGTSTP 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)
{
	if(verbose)
		printf("sigchld_handler: entering\n");
	pid_t pid;
	int status;
	struct job_t *job = NULL;
	while((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0){
		if(verbose){
			printf("sigchld_handler: Job [%d] (%d) deleted\n", pid2jid(pid), pid);
			if(WIFEXITED(status)){
				printf("sigchld_handler: Job [%d] (%d) terminated OK\n", pid2jid(pid), pid);
			} else if (!WIFSTOPPED(status)) {
				printf("sigchld_handler: Job [%d] (%d) terminated with error\n", 
					pid2jid(pid), pid);
			}
		}
		if(WIFSTOPPED(status)){
			printf("Job [%d] (%d) stopped by signal %d\n", pid2jid(pid), pid, WSTOPSIG(status));
			job = getjobpid(jobs, pid);
			job->state = ST;
		} else if (WIFSIGNALED(status)){
			printf("Job [%d] (%d) terminated by signal %d\n", pid2jid(pid), pid, WTERMSIG(status));
			deletejob(jobs,pid);
		} else{
			deletejob(jobs,pid);
		}
	}
	if(verbose)
		printf("sigchld_handler: exiting\n");
  return;
}
void sigchld_handler ( int sig ) { if ( verbose ) printf ( " \n " ) ; pid_t pid ; int status ; struct job_t * job = NULL ; while ( ( pid = waitpid ( -1 , & status , WNOHANG | WUNTRACED ) ) > 0 ) { if ( verbose ) { printf ( " \n " , pid2jid ( pid ) , pid ) ; if ( WIFEXITED ( status ) ) { printf ( " \n " , pid2jid ( pid ) , pid ) ; } else if ( ! WIFSTOPPED ( status ) ) { printf ( " \n " , pid2jid ( pid ) , pid ) ; } } if ( WIFSTOPPED ( status ) ) { printf ( " \n " , pid2jid ( pid ) , pid , WSTOPSIG ( status ) ) ; job = getjobpid ( jobs , pid ) ; job -> state = ST ; } else if ( WIFSIGNALED ( status ) ) { printf ( " \n " , pid2jid ( pid ) , pid , WTERMSIG ( status ) ) ; deletejob ( jobs , pid ) ; } else { deletejob ( jobs , pid ) ; } } if ( verbose ) printf ( " \n " ) ; return ; }
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 or SIGTSTP signal.
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 or SIGTSTP signal .
// Checks to see if any children are terminated or stopped, reaps them and removes them from the job list  // if terminated and sets them to the state ST if stopped. // If the state of the process changed state due to a signal, the responsible signal is output to stdout.