Does waitid consume SIGCHLD? - c

Do waitid/waitpid consume any pending SIGCHLD?
E.g., if one thread calls waitid while another one calls sigwaitinfo or reads from signalfd, can I assume that both calls return correct data when the child process terminates?

Found https://lkml.org/lkml/2009/1/10/181 :
That notification only tells us that at least one process has died;
SIGCHLD may only be pending once at a time. If further children die
before we clear the signal, nothing will happen.
...
Because it only tells us that at least one process has died, we have
to call waitpid() repeatedly until we have exhausted the wait queue.
~~Calling waitpid() does not clear the pending signal.~~
Мanpages do not mention "wait queue", but it explains a few things.

I wouldn't do that. The problem is that you do not know in which thread a signal is delivered (first). On the other hand sigwaitinfo() removes the signal from the pending signals set. So the thread calling waitpid() may never return.

Related

Why we generally ignore SIGCHLD

I was studying about signals and going through this link
https://en.wikipedia.org/wiki/Child_process#cite_note-1
And this is what it says : "The SIGCHLD signal is sent to the parent of a child process when it exits, is interrupted, or resumes after being interrupted. By default the signal is simply ignored"
is there any reason why we ignore SIGCHLD.
Try having kids and you'll understand why sometimes you have to ignore SIGCHLD to maintain your sanity :).
Jokes aside, all that statement means is that POSIX systems do not define a default signal behavior, other than to ignore it, for SIGCHLD. Compare this with SIGINT, SIGTERM, etc where the default behavior might be to terminate the process.
See man 7 signal on linux for a list of all signals, all default handlers, and the mapping of signals->default handler.
Often it makes sense to ignore SIGCHLD because you can know everything you need to know from waitpid.
Even though my answer is late, it might be helpful for a wonderer person thinking reason for need of SIGCHLD and why it is ignored. Let's listen my story.
I've taken a project in which we are streaming online radio stations whose extensions are .pls, .m3u or just IP:Port. Each station is a channel for us. There are two doodads - a potentiometer and a rotary encoder - which are able to be rotated(switched) either clockwise or counter clockwise. The former is used to adjust volume of the radio, likewise the latter is to change channels. I'm using a media player working via terminal, so it is also another process. Likewise, I'm using amixer which is also additional another process to adjust volume abruptly within a while infinite loop . In the main process, I create two processes. To change channel I opt to send SIGKILL signal to terminate the player process which is liable to play selected station to go new channel and wait() in parent. wait() usage is appropriate here because I had killed him before I waited. It would immediately returns without blocking. On the volume changer's side, it works until radio device is turned off. Its process is being run in an infinite loop.
So, what would be happen if I opt to make wait its parent process for the volume adjuster process?
The main process would block forever since the volume adjuster process would never return. In lieu, I opt to handle explicitly but in ignoring way. Why? Because I don't care when it is terminated or what its return value is. I only care that after its termination, I don't want the child to turn into a zombie. I just want when the child exits it is reaped immediately as well as non-blocking main process.
Why do we generally ignore SIGCHLD?
If (as in the aforementioned example) the signal handler does nothing beyond calling waitpid then an alternative is available. Setting the SIGCHLD handler to SIG_IGN will cause zombie processes to be reaped automatically.
Don't forget that to do that, explicitly calling sigaction() with the disposition SIG_IGN is needed.

pthread_kill doesnt kill thread C linux

i am making a small project which will be incorporated into larger project. basically what it does is keeps track of threads that are created by way of adding them to a main struct which keeps track of what the thread does (its main function) and its pthread_t id. the other struct keeps track of the data to be passed to the function and the element number of where the pthread_t id is stored inside threads[]. its a bit micky mouse and it jumps around a bit but it all works besides when it is time to kill the thread. i get no segfaults and no errors and the program finishes fine, but the thread does not get killed when pthread_kill() is called (the function returns 0 meaning no error and it worked) although the thread continues to run until the main application returns.
pthread_kill() will not kill a thread. The only difference with kill() is that the signal is handled by the designated thread and not handled while that thread has the signal masked (see pthread_sigmask()). A signal like SIGTERM will by default still terminate the entire process.
If you are considering to call pthread_exit() from a signal handler, you should probably use pthread_cancel() instead.
Cancellation is safe if all code that may be cancelled cooperates (or the code that calls it disables cancellation for the time). Most libraries do not care about this, though.
A safer method is to ask the thread to exit without any force, such as by sending a special message to it (if the thread normally processes messages).
Alternatively, don't bother to kill any threads and just call _exit(), _Exit() or quick_exit().
From http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_kill.html
As in kill(), if sig is zero, error checking is performed but no signal is actually sent.
so the following
pthread_kill(threads[i].tID, 0);
Wont actually kill the thread. You need to use an actual signal to kill a thread. A list of signals can be found here:
http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html

Is kill function synchronous?

Is the kill function in Linux synchronous? Say, I programatically call the kill function to terminate a process, will it return only when the intended process is terminated, or it just sends the signal and return. If that is the case, how can I make it wait for the intended process to be killed?
No, since it doesn't kill anything, it only sends a signal to the process.
By default this signal can even be blocked or ignored.
You can't block kill -9 which represents sending SIGKILL
To wait for the process to die:
while kill -0 PID_OF_THE_PROCESS 2>/dev/null; do sleep 1; done
kill cannot be synchronous as it only sends a signal. The target process might ignore incoming signals (cf. SIG_IGN) so there's no guarantee regarding kill's effect.
It shouldn't be difficult to make an experiment verifying this hypothesis. Start process A and make it handle SIGTERM with a 10 second sleep before dying. Then start process B, which delivers a SIGTERM to A and exits immediately.
The kill system call does not wait for the other process to do anything. The signal is posted to the target process and the system call returns. The target process notices the signal when it is scheduled to run.
No. man 2 kill
man wait
See also man 7 signal for more details about Unix signals.

how to handle multiple signals by order of arrival in C

I want to be able to handle many signals of the same type (SIGCHLD), but, I want to make sure that if a signal is arriving while I'm still handling the previous one, I will finish handling the first to arrive, and only after I finish handling it, I'll handle the next ones.
There may be more than one signals waiting to be handled.
Also, does a process sends SIGCHLD if it's terminated or killed (using SIGTERM/SIGKILL) by the parent process?
As long as you use sigaction and not the problematic signal function to setup your signal handler, you can be sure (unless you specify otherwise) that your signal handler will not be interrupted by another occurrence of the signal it's handling. However it's possible if many child processes all die at once that you might not receive a signal for each. On each SIGCHLD, the normal procedure is to attempt to wait for children until your wait-family function says there are no children left to wait for. At this point, you can be sure that any further child termination will give you a new SIGCHLD.
Also, since you're very restricted as to what functions you can use from a signal handler, you'd probably be better off just setting some sort of flag or otherwise notifying your main program loop that it should check for terminated children via one of the wait interfaces.
And finally, yes, a SIGCHLD is delivered regardless of the reason the child terminated - including if it was killed by the parent.

How does a "kill" work? And especically how does a "kill" work on blocked proces?

Who in the kernel is responsible for killing a process.
What if a "kill" comes, and the process is in the blocked state. Does the kill waits until the process comes to running state to clean himself.
If someone can answer more in terms of kernel, like when a SIGINT from the kill command is generated, what all is invoked by the kernel until the TCBs (task control blocks) are cleared in the end.
I presume you are talking about SIGKILL, so I will confine the discussion to that signal only.
When a process raises a SIGKILL on another process, SIGKILL is added as a pending signal on the victim process, and any pending SIGSTOP, SIGTSTP, SIGTTOU or SIGTTIN signals are cleared. The victim is woken up (made runnable) if it is stopped or in an interruptible sleep state.
When the victim process next attempts to go from Kernel mode to User mode, the pending signals are checked. This is where the pending SIGKILL is found, and the Kernel calls do_exit() instead of going back to User mode.
The transition from Kernel mode to User mode will be when the process is next scheduled (unless it was in an uninterruptible sleep - this is the infamous D state). If it's in an uninterrutible sleep, the process won't try to go back to User mode until its woken.
Killing it with a signal other than SIGKILL, just causes a signal to be sent. This can be masked or ignored, but assuming it isn't (or after it's unmasked), then it interrupts the normal running of the program.
If an IPC-type system call is in progress (e.g. reading from a socket, select(), poll(), sleep() etc), then it will be interrupted and fail with EINTR in errno. A properly written application will re-issue the call after handling the signal.
The process then immediately executes a call to the signal handler, which may return to allow processing to continue, or it could call longjmp (in C), or it could exit the process, which is normally the default.
SIGKILL is completely different, none of the above happens. Instead it just quits the system call (which would presumably leave EINTR in errno, if the process was allowed to read it), then causes the task to exit immediately with no possibility to handle it.
But either of them I think waits for a "D" "uninterruptable sleep" state to finish. This would normally be something like a blocking disc read, page fault demand-load or something.
Running kill simply sends a signal to the process (TERM) asking it nicely to terminate. If it won't respond that's it's business. However, you can choose to send any one of several different signals commanding it to go away. What you may be interested in is kill -9 (SIGKILL) which kills it without giving it a choice in the matter.
(Edit: As was pointed out in the comments, TERM is the default)
Killing (rather than interrupting) is usually performed by the SIGKILL signal in UNIX systems (CTRL-C sends SIGINT).
These systems usually provide a method of interrupting blocking system calls by a signal, which allows the signal handler to execute without waiting on a system call to complete (This is where the EINTR error comes into play). So normally, the call is just cancelled, without waiting for it to complete.
Each process can recieve many types of signal, which it can ignore to handle but few aren't delivered to process but "Proceess scheduler" terminates the process....
see this for more explanation
http://www.linux-tutorial.info/modules.php?name=MContent&pageid=289

Resources