Does a process whose parent has died normally continues execution? - linux

I know that a child process whose parent has died becomes a zombie process but when that happens, does it continue execution normally ?
What I have read so far seems to suggest that yes but I have not found confirmation and my programming ventures seems to suggest otherwise.

Whether a child's parent has exited has no effect on whether it continues running. Assuming the child has access to the resources that it needs, it will continue to run normally.
This is important when writing a daemon, since typically the started process forks twice, and it is the grandchild that ultimately runs as a service.
Note that there are some reasons a child may end up exiting abnormally due to a parent exiting. For example, if the parent is an interactive shell and it exits, the terminal may disappear, and as a result the child may receive a SIGHUP. However, in that case, the reason the child will have exited is because it received a signal it didn't handle, and if it had set up a suitable handler, it would have continued running.

Related

Why do we need a wait() system call?

Hello I am new to learning about system calls. I am currently learning about fork() and wait() system calls. I know that fork() creates a new child process. What confuses me is the wait() call.
This is what I understand so far:
(1) When a process dies, it goes into a 'Zombie State' i.e. it does not release its PID but waits for its parent to acknowledge that the child process has died and then the PID is released
(2) So we need a way to figure out when the child process has ended so that we don't leave any processes in the zombie state
I am confused with the following things:
(1) When running a C program where I fork a new child process, if I don't call wait() explicitly, is it done internally when the child process ends? Because you could still write a block of code in C where you run fork() without wait() and it seems to work fine?
(2) What does wait() do? I know it returns the PID of the child process that was terminated, but how is this helpful/related to releasing the PID of the terminated process?
I am sorry for such naive questions but this is something I was really curious about and I couldn't find any good resources online! Your help is much appreciated!
wait isn't about preventing zombie states. Zombie states are your friend.
POSIX more or less lets you do two things with pids: signal them with kill or reap them (and synchronize with them) with wait/waitpid/waittid.
The wait syscalls are primarily for waiting on a process to exit or die from a signal (though they can also be used to wait on other process status changes such as the child becoming stopped or the child waking up from being stopped).
Secondarily, they're about reaping exit/died statuses, thereby releasing (zombified) pids.
Until you release a pid with wait/waitpid/waittid, you can continue flogging the pid with requests for it to die (kill(pid,SIGTERM);) or with some other signal (other then SIGKILL) and you can rest assured the pid represents the process you've forked off and that you're not accidentally killing someone else's process.
But once you reap a zombified pid by waiting on it, then the pid is no longer yours and another process might take it (which typically happens after some time, as pids in the system typically increment and then wrap arround).
That's why auto-wait would be a bad idea (in some cases it isn't and then you can achieve it with globally with signal(SIGCHLD,SIG_IGN);) and why (short-lived) zombies states are your friend. They keep the child pid stable for you until you're ready to release it.
If you exit without releasing any of your children's pids, then you don't have to worry about zombie children anymore--your child processes will be reparented to the init process, which will wait on them for you when they die.
When you call fork(), a new process is created with you being its parent. When the child process finishes its running with a call to exit(), its process descriptor is still kept in the kernel's memory. It is your responsibility as its parent to collect its exit code, which is done with a call to wait() syscall. wait() blocks the parent process until one of its childrens is finished.
Zombie process is the name given to a process whose exit code was never collected by its parent.
Regarding to your first question - wait() is not called automatically as zombie processes wouldn't exist if it did. It is your responsibility as a programmer. Omitting the call to wait() will still work as you mentioned - but it is considered a bad practice.
Both this link and this link explains it good.

does Node kill spawned child processes automatically?

In the documentation for Node's Child Processes, there is this sentence in the section on child_process.spawn():
On Windows, setting options.detached to true makes it possible for the
child process to continue running after the parent exits.
That makes it sound like (at least on Windows) when you leave options.detached to the default value of false, spawn()'d processes will automatically be killed. That's actually the behavior I want in my application, and in fact I was calling myChildProcess.kill( "SIGINT" ) in my code, but commented it out, and the child processes still went away when my app quit. So that's great, but:
(1) My understanding is that it's necessary to do some tricky stuff with "job objects" as discussed here in order to make this work on Windows. Do you know if Node is doing something tricky like that to make child processes go away? Or perhaps it's more simple than that and Node just keeps a list of the spawned process IDs and kills any of them that are still around when shutting down? Which leads to the closely related question...
(2) If Node is indeed doing something special to kill child processes, do you know if there are cases (e.g., some kind of app crash) that would defeat what it's doing and leave the child processes running?
UPDATE: To clarify, the child processes I'm launching in my case are Python web server processes, not other Node processes. I don't know if there's a difference in behavior between a Node child process and some other child process for the purpose of this question.
A Node instance will quit as long as there is nothing left in the event queue (and no async code pending), so as long as you aren't leaving anything open then naturally a Node process will quit when it's done.
In terms of the process hanging on a crash, unless you are explicitly handling uncaught exceptions the the process will exit immediately.
If you want a child process to be long-running and to survive the termination of the node process itself, as you know you set options.detached = true.
This business of stopping a child process when a parent process stops is operating-system behavior. A parent process (running any programming language system, not just node) owns a non-detached child process. The OS cleans up child processes upon the termination of their parent.
Detaching a process tells the OS to make it no longer a child process, so the OS won't clean it up automatically.
A good practice for node child processes: whenever possible, have them do their assigned task and then exit. In other words, in most cases you should not need to rely on this child / detached behavior.

Proper way to use fork() and wait()

I have just started learning about fork and wait in Linux and came across this paragraph in the wait() manual page notes:
A child that terminates, but has not been waited for becomes a "zombie". The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. As long as a zombie is not removed from the system via a wait, it will consume a slot in the kernel process table, and if this table fills, it will not be possible to create further processes. If a parent process terminates, then its "zombie" children (if any) are adopted by init(8), which automatically performs a wait to remove the zombies.
A question that came to mind after reading this:
Isn't the fact that not using wait() causes a resource waste until the parent terminates, a problem that amplifies when the parent process is meant to be a long lived process in the system?
Does this means I should always use wait() as soon as possible after using fork?
Isn't the fact that not using wait() will cause a resource waste until
the parent will terminate?
When a child process is running, there's no wastage of resource; it's still doing its task. The resource waste that your citation talks about is only when a child dies but it's parent hasn't reaped it yet i.e. not wait()ed on the child process.
a problem that amplifies when the parent process is meant to be a long
lived process in the system?
When your application runs for a very longtime and keeps forking children, there's a chance that the system might run out of resources when many child process are still running or the parent process didn't reap the exited children. It's the job of the application process to to optimally manage the resources on the system and reaping the child processes as soon as they might have done.
Does this means I should always use wait() as soon as possible after
using fork?
There's no straight "as early" or "as late" kind of answer to this. For example, parent process might want to carry on do something useful when the child is still running rather than waiting (It might be unnecessary to even check periodically if children status with WNOHANG when parent knows the children might have a long tasks to finish). So in this case, waiting as soon as forking a process might not be what you want. In general, parent should call wait() whenever it expects the child(ren) to have completed its task (or wants to know the stauts of children). The responsibility lies with the programmer to code correctly and call wait() at the most appropriate time.

Why is a zombie process necessary?

Wikipedia basically gives all the possible information about zombie processes that I NEED to know but just a simple line on how it might be useful..in that a conflict in PIDs will not exist in the event the parent process creates another child process.
How is this then actually "useful"? Wouldn't the PID be then available if the named zombie process were to be removed instead of being kept there?
Or are there any other reasons as to why the zombie process should exist?
Zombie processes are actually really important and definitely need to exist. First it's important to understand how process creation works in Unix/Linux. The only way to create a new process is for an existing process to create a new child process via fork(). In this way, all of the processes on the system are arranged in a nice orderly tree heirarchy. Try running ps -Hu <your username> on a Linux system to see the heirarchy of processes that you own.
In many programs it is critically important for a parent process to be able to obtain basic information about its child processes that have exited. This basic information includes the exit status and resource usage of the child. When the parent is ready to get information about a dead child process it calls one of the wait() functions to wait for a child to exit and obtain exit status and resource usage info.
But what happens if a child process exits before the parent waits for it? This is where zombie processes become necessary. The operating system can't just discard the child process; the operation of the parent process may be dependent upon knowing the exit status or resource usage of the child. i.e. The parent process might need to know that the child exited abnormally, or it might be collecting CPU usage statistics for its children, etc. So, the only choice is to save off that information and make it available to the parent when it finally does call wait(). This information is what a zombie process is and it's a critical part of how process management works on Unix/Linux. Zombie processes allow the parent to be guaranteed to be able to retreive exit status, accounting information, and process id for child processes, regardless of whether the parent calls wait() before or after the child process exits.
This is why a zombie process is necessary.
Footnote: If the parent process never calls wait(), then the child process is reparented to the init process when the parent process dies, and init will wait() for the child.
The answer is on Wikipedia as well, which is:
This entry is still needed to allow the parent process to read its
child's exit status.
Zombie processes are useful.
Zombie processes allow the parent to be guaranteed to be able to retrieve exit status, accounting information, and process id of the child processes.
A process that doesn't clean up its child zombies isn't programmed properly.

reading the exit value of a defunct process

I have a dead process that is now in the defunct state which means that its parent process has not read its exit value. (and it is not going to read it)
I know that the exit value is stored somewhere in the kernel for the parent process to read but, is there a way for me to read that value if I am not the parent process ?
Ideally, I would be able to do this from a shell or an abritrary C/python/your-favorite-language program.
[edit]: This is not a question on how to reap the child or kill it. I do not care if it uses up a slot in the process table. I just want to know what its exit value is. i.e., I would like to read task_struct->exit_code in the kernel.
Mathieu
One thing you might be able to do is to send the parent SIGCHLD, which tells it that a child has died. If the program is of any quality, it will reap the process.
kill -s SIGCHLD parentpid
No. Attempting to call waitpid() for a process that is not one of the calling process's children will result in ECHILD. You will need to kill the parent process, causing the child to reparent to init, which will subsequently reap it.

Resources