### 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) ---- ![](https://i.imgur.com/2yNWrpl.png) ---- ![](https://i.imgur.com/lT54Bvq.png) ---- 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}]"}
    573 views
   Owned this note