ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The "zombie process" state is defined so that the parent process can easily rendezvous with the terminated child in order to collect its final status. It avoids a "race condition."
Specifically: When the child process ends, it must signal its parent. However, there will now be an unpredictable delay until the parent process, having been signaled, actually is dispatched to run on a particular CPU or core. During this interval, the dead child's process-table entry is marked as a "zombie," so that it won't be garbage-collected or re-used until the parent gets a chance to read it. Once the parent process has done so, the child's process-table entry can be discarded.
Since process-table zombies could "pile up" if the parent didn't attend to this duty, Linux takes sensible steps to prevent it. You must clean-up after your own kids.
Usually, parent-processes relegate all of their duties to their children. (Yeah, just like in real life ... ) Consider, for example, the classic init process: it forks a bunch of processes, then sits around and waits for them to die. It maintains the pool of processes according to the inittab, and it is the "grim reaper of last resort" for any orphans, but it does not, itself, do anything besides that. With this strategy, the overall design is greatly simplified and race-conditions are eliminated. The parent process maintains the pool of worker-children, but it does not do the work itself. It does not "wait on" anything other than child-termination.
The parent doesn't have to block while waiting either, waitpid() can be invoked with zero timeout so it won't block, but as stated, the parent is responsible to check for signals from the child as part of the closure for the lifespan of the child processes. I'm not sure it will always be SIGCHLD and in fact to me I wait on the child pid and then check exit status, many times I believe it is SIGTERM that I see, which indicates that the child exited normally. In fact, if the child was terminated by a signal; such as SIGKILL, then the status will indicate that the child was terminated by a signal and you can extract the signal from the status. There are several macros available, see waitpid(2) for information: WIFEXITED(status), WEXITSTATUS(status), WIFSIGNALED(status), WTERMSIG(status), WISTOPPED(status), WSTOPSIG(status) are some of the macros which return the relevant desired information from the status.
That being said, and perhaps for the reasons said, I happen to think that by-far the cleanest design is to have a "father process" that does nothing except to manage the children. The process does a waitpid(), with no timeout, and to properly attend to whatever “child re-launching” responsibilities might be called-for based on which particular child terminates. (In fact, I have seen more than one system which actually more or less re-used init as its father-process ...)
In such a system design, child-processes do everything, including "soliciting incoming requests and waiting for them to arrive," and/or "disposing of completed requests." The father-process is aware of the individual requirements of each of its children, but in the overall scheme of what-it-is that the total system is doing, its role is totally passive.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.