Shell Problem: How to manage terminated or stopped child process.
In both cases, a SIGCHLD is sent to the parent.
Signal handler for SIGCHLD is the one place to handle both events.
What needs to be done in this signal handler for the two cases?
- If a child process terminated, it should be removed from the job table.
- If a child was stopped, its state should be changed in the job table.
When the SIGCHLD signal is received, the signal handler needs to know what child changed state and whether it terminated or stopped.
The handler can call waitpid with the right parameters to get this information.
Since signals are not queued, the handler must call waitpid for all processes that have already terminated or stopped, but must not block!
What are the correct parameters to use?
waitpid parameters | wait set | blocks if | return value |
---|---|---|---|
waitpid(-1, &status, 0) | terminated children | children still exist, but none have terminated | pid of a terminated child or -1 if wait set empty |
waitpid(-1, &status, WUNTRACED) | terminated OR stopped children | children still exist, but none have terminated OR stopped | pid of a child in the wait set or -1 if no more children |
waitpid(-1, &status, WNOHANG) | terminated children | never blocks | pid of a child in the wait set or 0 if children still exist, but none have terminated or -1 no more children |
waitpid(-1, &status, WNOHANG | WUNTRACED) | terminated or stopped children | never blocks | pid of a child in the wait set or 0 if children still exist, but none are terminated or stopped or -1 if no more children exist |