Reputation: 66415
I'm working on a server code that uses fork()
and exec to create child processes. The PID of the child is registered when fork()
succeeds and cleaned up when the CHILD
signal has been caught.
If the server needs to stop, all programs are killed, eventually with a KILL signal. Now, this works by means of iterating through all registered PIDs and waiting for the CHILD signal handler to remove the PIDs. This will fail if child program did not exit properly. Therefore I want to use kill
in combination with waitpid
to ensure that PID list is cleaned up and log and do some other stuff otherwise.
Consider the next code sample:
kill(pid, SIGKILL);
waitpid(pid, NULL, WNOHANG);
Excerpt from waitpid(2)
:
waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned.
Is the process given by pid
always gone before the next function kicks in? Will waitpid
always return -1
in the above case?
Upvotes: 13
Views: 10588
Reputation: 6730
JFYI there is also the option of pidfd_send_signal()
. From the manual:
The pidfd_send_signal() system call allows the avoidance of race conditions that occur when using traditional interfaces (such as kill(2)) to signal a process. The problem is that the traditional interfaces specify the target process via a process ID (PID), with the result that the sender may accidentally send a signal to the wrong process if the originally intended target process has terminated and its PID has been recycled for another process. By contrast, a PID file descriptor is a stable reference to a specific process; if that process terminates, pidfd_send_signal() fails with the error ESRCH.
You can see an example on how to use it here.
Upvotes: 0
Reputation: 66263
Is the process given by pid always gone before the next function kicks in?
There is no guarantee for that. On a multiprocessor your process might be on CPU 0 while the cleanup in the kernel for the killed process takes place on CPU 1. That's a classical race-condition. Even on singlecore processors there is no guarantee for that.
Will waitpid always return -1 in the above case?
Since it is a race condition - in most cases it perhaps will. But there is no guarantee.
Since you are not interested in the status, this semicode might be more appropriate in your case:
// kill all childs
foreach(pid from pidlist)
kill(pid, SIGKILL);
// gather results - remove zombies
while( not_empty(pidlist) )
pid = waitpid(-1, NULL, WNOHANG);
if( pid > 0 )
remove_list_item(pidlist, pid);
else if( pid == 0 )
sleep(1);
else
break;
Upvotes: 10
Reputation: 36049
The KILL
signal handler will run during the killed processes CPU time. This is potentially much later than your waitpid
call, especially on a loaded system, so waitpid
can very well return 0.
Upvotes: 5