Well, I'm learning about processes using the C language, and I have seen that when you call the exit function a process is terminated and without waiting for it, it will become a zombie process. My question is, if the first process created when executing the program is a process itself, is there a 0S routine that wait for it after an exit() call, avoiding that it becomes a zombie process? I'm curious about it.
For Unix systems at least (and I expect Windows is similar), when the system boots, it creates one special first process. Every process after that is created by some existing process.
When you log into a windowed desktop interface, there is some desktop manager process (that has been created by the first process or one of its descendants) managing windows. When you start a program by clicking on it, that desktop manager or one of its children (maybe some file manager software) creates a process to run the program. When you start a program by executing a command in a terminal window, there is a command line shell process that is interpreting the things you type, and it creates a process to run the program.
So, in all cases, your user program has a parent process, either a command-line shell or some desktop software.
If a child process creates another child (even as the first instruction) then the parent also has to wait for it or it becomes a zombie.
Basically processes always become zombie until they are removed from the process table, the OS (via the process init) will handle and wait() for orphans (zombies without parents), it does that periodically so normally you won't have orphans running for very long.
On Linux, the top most (parent) process is init. This is the only process, which has no parent. Any other process (without any exception) do have a parent and hence is a child of another process.
See:
init
Section NOTES on wait
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(1), ... init(1) automatically performs a wait to remove the
zombies.
Related
I'm trying to write a mock-shell in c on linux, and got stuck on this problem:
I need to run some processes in the background, and some processes in the foreground.
To prevent the foreground processes from becoming zombies, I can use wait(), but how do I prevent the background processes from becoming zombies?
You cannot prevent any process from becoming a zombie, but you can limit the time that it remains one. A process is a zombie from the time it terminates to the time its parent collects it via a call to wait() or waitpid() or another function serving that purpose. That time can be made very short indeed, for instance if the parent process is already waiting when the child terminates, but termination and subsequent collection are not synchronous.
The distinction between background and foreground processes is primarily about control of a terminal; it has little to do with a parent shell managing child processes. You collect child processes belonging to background jobs via wait(), etc., exactly the same way you collect child processes belonging to foreground jobs. You can can collect already-terminated children without waiting for unterminated ones by using waitpid() with the W_NOHANG flag, as #Someprogrammerdude already described. It remains to insert such waits at an appropriate time, and it seems common for interactive shells to schedule that around reading commands from the user.
You can poll for the, using waitpid with the W_NOHANG flag. Or you could add a SIGCHLD handler which will be invoked each time a child-process ends (or have other status changes).
" Thus, the common method for launching a daemon involves forking once or twice, and making the parent processes die while the child process begins performing its normal function."
I was going through OS concepts and I didn't understand the above said lines.
Why the parent process will be made to exit( or parent dying ),in the process of creating a Daemon?
Can someone pls explain me.
Traditionally, a daemon process is defined as a process whose parent is the system's init process and which runs in the background. For instance, if you were to execute some program in your terminal, your shell would create a process (either in the foreground or background) and the program would run with your shell as its parent. This is an example of a non-daemon process because its parent is your shell process.
So how do you produce a process whose parent is the init process? Well, a process whose parent process dies before it (the child) has exited becomes an orphan process. An orphan process will in turn be re-parented to the init process. Voila, the process now meets the definition of a daemon.
Tying this back to your quote, if you were to fork once and then kill the parent, you achieve the desired effect. Likewise, if you fork once and then have that child fork another process, followed by killing the first child, you also achieve the desired effect while keeping the (now grandparent) process alive.
This is not a requirement, as any background process could be a daemon. Technically a daemon process in one that runs to operate some general non interactive task. In Unix environment, a daemon is generally set as a process that have some characteristics: no controlling terminal, no umask, particular working directory, etc. Forking twice is a common way to obtain the grandchild to be inherited by init process and have the former properties, in some way to get a process fully detached of any user control (except root of course).
This applies only if a standard user want to create a daemon. Some other standard daemons are created almost normally (see init, launchd, etc)
If the parent exits while the daemon continues running, the daemon is orphaned, and the init process typically adopts it (i.e. becomes the parent).
There are some exceptions, but it is normally expected that a daemon process will be descended from the init process (e.g. the init process will launch daemons during system startup). So, if another process launches a daemon and terminates, it achieves the desired effect.
Note that some other actions are also needed, such as disassociating the daemon from any tty window.
Other answers already explained what happens when parent dies i.e. child is adopted by init process.
But why above is required to make a process daemon? A daemon by definition is non-interacting program i.e. it should not be associated with a terminal. That ensures that daemon continues to work in background even when user sends signals by Control-C, hangup etc. Now, how to prevent a process from ever attaching to a terminal? Make init it's parent by killing original parent.
init is a special process because:
It's not attached to any terminal.
It's first process (pid 1) after booting OS, and that makes it leader of it's session. Note that every UNIX process belongs a process group and that in turn belongs to a session. First process in the session becomes session leader.
In UNIX, only session leader can attach to (or control) terminal. As soon as you make init parent of your process, it joins init's session. Since init is the session leader, your process can never be the leader and hence can never attach to a terminal. That's what we wanted, right?
There are other ways to detach terminal e.g. calling setsid but that's not part of this discussion.
Ina console application, passing _P_OVERLAY to a spawn function (which has the same effect as calling exec), destroys the current process.
This would be the desired behavior if it were not for the fact that doing so causes the calling process (which is often cmd.exe) to assume its callee has returned, whereas in reality the spawned sub-process of that callee is still running and therefore the caller should wait for that callee to terminate before continuing to use the console.
So, if the caller is cmd.exe (the command prompt), what happens is that as soon as the callee spawns the sub-process, the user is immediately prompted with the C:\Users\User> prompt, and becomes free to type in more commands, even though the sub-process is still running.
The best solution I have is to avoid terminating the current process until the child has terminated, but I'm wondering: is there any way to have the calling process wait on the spawned sub-processes before continuing when the callee has terminated?
No, there is no way to do this - if you want cmd.exe to wait for your child to exit, then you need to wait for your child to exit.
The reason is that when cmd.exe launches your process it receives a process handle; it then waits for that process handle to become signaled. Most other parents (for example, the C runtime library) will behave the same way. Process handles are signaled when the process they refer to exits, and there is no way to change that behaviour.
Workaround: presumably you are using _P_OVERLAY because you're porting from UNIX code. If there is too much code to conveniently change all of the instances to wait for the child before exiting, you could start a child process as soon as your process starts, and run all of the UNIX-based code in the child. In this model, the only thing the top-level process does is to wait for the rest of the process tree to exit. (You can use a job object to keep track of the process tree.)
I was trying to write a basic multiprocessing tcp-server, which forks a process for every new accept().
I don't need the parent process to wait on the child processes. I have come across two solutions- forking twice and daemonising.
What's the difference between the two?
Which is more suitable in this scenario?
What are the factors that are to be kept in mind for choosing one amongst these?
There is a subtle difference.
Forking twice: Intermediate child process can't become a zombie provided it has exited and has been waited for by Parent. Grandchild can't become a zombie either as it's parent (intermediate child process) has exited, so grandchild is an orphan. The orphan(grandchild) gets inherited by init and if it exits now, it is the responsibility of the system to clean it up. In this way, the parent process is releived of the responsibility of waiting to collect the exit status signal from child and also the parent can be busy doing some other work. This also enables the child to run for long time so that a shorttime parent need not wait for that amount of time.
Daemon: This is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons. Has no controlling terminal.
The decision of approach depends on the requirement/scenario in hand.
You do need the parent process to (eventually) wait() for each of its child processes, else the children will hang around until the parent exits. This is a form of resource leak.
Forking twice, with the intermediate process exiting immediately after forking, allows the original process to collect the child immediately (via wait()), and makes the grandchild process an orphan, which the system has responsibility for cleaning up. This is one way to avoid accumulating zombie processes. The grandchild remains in the same process group (and thus the same session) as the original process.
Daemonizing serves a somewhat different purpose. It puts the resulting (child) process in a new session (and new process group) with no controlling terminal. The same effect can be achieved by forking once, with the parent immediately calling _exit() and the child calling setsid().
A system service daemonizes to escape the session in which it was launched, so as not to be shut down when that session ends. This has little to do with multiprocessing, but a lot to do with process management. A process double-forks to avoid process management duties for the (grand)child processes; this has both multiprocessing and process management aspects.
Note, too, that double-forking doesn't just pass off process-management responsibilty, it also gives up process-management ability. Whether that's a good trade-off is situation-dependent.
When I call kill() on a process, it returns immediately, because it just send a signal. I have a code where I am checking some (foreign, not written nor modifiable by me) processes in a loop infinitely and if they exceed some limits (too much ram eaten etc) it kills them (and write to a syslog etc).
Problem is that when processes are heavily swapped, it takes many seconds to kill them, and because of that, my process executes the same check against same processes multiple times and attempts to send the signal many times to same process, and write this to syslog as well. (this is not done on purpose, it's just a side effect which I am trying to fix)
I don't care how many times it send a signal to process, but I do care how many times it writes to syslog. I could keep a list of PID's that were already sent the kill signal, but in theory, even if there is low probability, there could be another process spawned with same pid as previously killed one had, which might also be supposed to be killed and in this case, the log would be missing.
I don't know if there is unique identifier for any process, but I doubt so. How could I kill a process either synchronously, or keep track of processes that got signal and don't need to be logged again?
Even if you could do a "synchronous kill", you still have the race condition where you could kill the wrong process. It can happen whenever the process you want to kill exits by its own volition, or by third-party action, after you see it but before you kill it. During this interval, the PID could be assigned to a new process. There is basically no solution to this problem. PIDs are inherently a local resource that belongs to the parent of the identified process; use of the PID by any other process is a race condition.
If you have more control over the system (for example, controlling the parent of the processes you want to kill) then there may be special-case solutions. There might also be (Linux-specific) solutions based on using some mechanisms in /proc to avoid the race, though I'm not aware of any.
One other workaround may be to use ptrace on the target process as if you're going to debug it. This allows you to partially "steal" the parent role, avoiding invalidation of the PID while you're still using it and allowing you to get notification when the process terminates. You'd do something like:
Check the process info (e.g. from /proc) to determine that you want to kill it.
ptrace it, temporarily stopping it.
Re-check the process info to make sure you got the process you wanted to kill.
Resume the traced process.
kill it.
Wait (via waitpid) for notification that the process exited.
This will make the script wait for process termination.
kill $PID
while [ kill -0 $PID 2>/dev/null ]
do
sleep 1
done
kill -0 [pid] tests the existence of a process
The following solution works for most processes that aren't debuggers or processes being debugged in a debugger.
Use ptrace with argument PTRACE_ATTACH to attach to the process. This stops the process you want to kill. At this point, you should probably verify that you've attached to the right process.
Kill the target with SIGKILL. It's now gone.
I can't remember whether the process is now a zombie that you need to reap or whether you need to PTRACE_CONT it first. In either case, you'll eventually have to call waitpid to reap it, at which point you know it's dead.
If you are writing this in C you are sending the signal with the kill system call. Rather than repeatedly sending the terminating signal just send it once and then loop (or somehow periodically check) with kill(pid, 0); The zero value of signal will just tell you if the process is still alive and you can act appropriately. When it dies kill will return ESRCH.
when you spawn these processes, the classical waitpid(2) family can be used
when not used anywhere else, you can move the processes going to be killed into an own cgroup; there can be notifiers on these cgroups which get triggered when process is exiting.
to find out, whether process has been killed, you can chdir(2) into /proc/<pid> or open(2) this directory. After process termination, the status files there can not be accessed anymore. This method is racy (between your check and the action, the process can terminate and a new one with the same pid be spawned).