### NP project1 supplementary
On handling terminate child processes
---
:::info
Implementation 1:
:::
`wait` for the child process
```cpp
pid = fork()
if (pid == 0) {
// Do child process stuff
} else {
wait(); // Wait for termination of child ps
}
```
----
Problem : Processing large data will hang forever
```shell
% cat largeFile.txt | number
^~~~~~~~~~~~~~~~~
// cat contents to the pipe
```
----
Problem : Processing large data will hang forever
```shell
% cat largeFile.txt | number
^
// The pipe is full.
```
----
Problem : Processing large data will hang forever
```shell
% cat largeFile.txt | number
^~~~~~~~~~~~~~~~~
// Blocked because cannot write to the pipe
```
----
Problem : Processing large data will hang forever
```shell
% cat largeFile.txt | number
^~~~~~
// Waiting for cat's termination
```
----
Problem : Processing large data will hang forever
```shell
% cat largeFile.txt | number
^~~~~~
// But cat is blocked!
```
---
:::info
Implementation 2:
:::
==Don't== `wait` for the child process
```cpp
pid = fork();
if (pid == 0) {
// Do child process stuff
} else {
// wait();
}
```
----
Problem : Wrong Ordering
(also leaves zombie processes)
###### Wrong
:::danger
```
% ls
% bin test.html
^~~~~~~~~~~~~~~
// "% " shows before ls's output
```
:::
###### Correct
:::success
```
% ls
bin test.html
%
```
:::
----
So we need to `wait` to preserve the ordering
```cpp
pid = fork();
if (pid == 0) {
// Do child process stuff
} else {
wait(); // This is a MUST
}
```
----
But do we need to wait for **all** of the commands?
```shell
% removetag test.html | number
```
```shell
% cat largeFile.txt | cat | cat | cat | cat
```
----
###### Recall that we use `wait` to wait until the child process finish
:::success
```
% ls | cat
bin test.html // <- parent wait until child finish
```
:::
----
###### ...and then we print a `% `
:::success
```
% ls | cat
bin test.html // <- parent wait until child finish
% // <- put %
```
:::
----
###### Q : Which commands' output are we actually waiting?
```shell
% removetag test.html | number
^~~~~~~~~~~~~~~~~~~ ^~~~~~
```
```shell
% cat largeFile.txt | cat | cat | cat | cat
^~~~~~~~~~~~~~~~~ ^~~ ^~~ ^~~ ^~~
```
----
###### A : The last one
```shell
% removetag test.html | number
^~~~~~
```
```shell
% cat largeFile.txt | cat | cat | cat | cat
^~~
```
###### because only the last command will possibly output to console.
---
:::info
Implementation 3:
:::
###### `wait` for the last command only!
```cpp
pid = fork();
if (pid == 0) {
// Do child process stuff
} else {
wait(last_command);
}
```
----
Looks great!
######
```shell
% removetag test.html | number
1
2 Test
3 This is a test program
4 for ras.
5
%
```
```shell
% cat largeFile.txt | cat | cat | cat | cat
LARGEFILE CONTENT...
%
```
----
Looks great!
```shell
% removetag test.html | number
1
2 Test
3 This is a test program
4 for ras.
5
%
```
```shell
% cat largeFile.txt | cat | cat | cat | cat
LARGEFILE CONTENT...
%
```
###### (except for leaving the zombie processes)
----

----

----
Zombies will occupy your system, leaving no space for creating new processes.
you're the only one who can protect the system.
---
:::info
Implementation 4:
:::
###### `wait` for the last command
###### and use `signal handler`s with non-blocking wait
```cpp
void childHandler(int signo);
signal(SIGCHLD, childHandler)
^~~~~~
// Determine the behaviour when SIGCHLD happens
(as before)...
```
----
```cpp
void childHandler(int signo){
int status;
while (waitpid(-1, &status, WNOHANG) > 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NON-BLOCKING WAIT
// Return immediately if no child has exited.
}
```
```cpp
// In Parent process...
waitpid(last_command_pid, &status, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BLOCKING WAIT
// Blocks until the child exit
```
----
Do we have zombie processes left?
```shell
% cat largeFile.txt | cat | cat | cat | cat
^~~
```
###### Wait by parent to preserver ordering
----
Do we have zombie processes left?
```shell
% cat largeFile.txt | cat | cat | cat | cat
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
###### signal handler will reap them whenever they exit
---
### Conclusion:
* Use `Blocking-wait` for the command that will output to console.
* Use `signal handler` with `Non-blocking wait` to prevent zombie processes.
---
### Ref:
* ###### waitpid : https://linux.die.net/man/2/waitpid
* ###### signal : http://man7.org/linux/man-pages/man7/signal.7.html
* ###### Last year's supplementory : See E3
{"metaMigratedAt":"2023-06-15T00:51:06.026Z","metaMigratedFrom":"YAML","title":"NP project1 supplementary","breaks":true,"description":"View the slide with \"Slide Mode\"","slideOptions":"{\"spotlight\":{\"enabled\":true}}","contributors":"[{\"id\":\"87e4bf47-0674-424e-81b2-47e6367febda\",\"add\":53,\"del\":86},{\"id\":\"f4b0ef1b-9af8-4893-9d19-a72796f225a7\",\"add\":7445,\"del\":2283}]"}