pthread_sigmask not working properly with aio callback threads - linux

My application is sometimes terminating from SIGIO or SIGUSR1 signals even though I have blocked these signals.
My main thread starts off with blocking SIGIO and SIGUSR1, then makes 2 AIO read operations. These operations use threads to get notification about operation status. The notify functions (invoked as detached threads) start another AIO operation (they manipulate the data that has been read and start writing it back to the file) and notification is handled by sending signal (one operation uses SIGIO, the other uses SIGUSR1) to this process. I am receiving these signals synchronously by calling sigwait in the main thread. Unfortunately, sometimes my program crashes, being stopped by SIGUSR1 or SIGIO signal (which should be blocked by a sigmask).
One possible solution is to set SIG_IGN handlers for them but this doesn't solve the problem. Their handlers shouldn't be invoked, rather should they be retrieved from pending signals by sigwait in the next iteration of the main program loop.
I have no idea which thread handles this signal in this manner. Maybe it's the init who receives this signal? Or some shell thread? I have no idea.

I'd hazard a guess that the signal is being received by one of your AIO callback threads, or by the very thread which generates the signal. (Prove me wrong and I'll delete this answer.)
Unfortunately per the standard, "[t]he signal mask of [a SIGEV_THREAD] thread is implementation-defined." For example, on Linux (glibc 2.12), if I block SIGUSR1 in main, then contrive to run a SIGEV_THREAD handler from an aio_read call, the handler runs with SIGUSR1 unblocked.
This makes SIGEV_THREAD handlers unsuitable for an application that must reliably and portably handle signals.

Related

Execution of Python signal handlers

I am new to python. I want to understand how python execute signal .I started reading the official documentation. The following statements doesn't make sense
1.Python signal handler does not get executed inside the low-level (C) signal handler. Instead, the low-level signal handler sets a flag which tells the virtual machine to execute the corresponding Python signal handler at a later point(for example at the next bytecode instruction).
2."Python signal handlers are always executed in the main Python thread of the main interpreter, even if the signal was received in another thread."
Can someone help me
When you are registering signal handlers, you primarily are opting for asynchronous handling of the signals. When the signal is received, the code execution jumps to those registered signal handlers (There are exceptions check sigaction). You can't do much in the signal handlers, and it is safe only to call async-signal-safe functions.
Python doesn't immediately jump to the signal handler (registered by the user) when the signal is received, and it instead jumps to the low-level C signal handler where it just queues what to execute later (Refer to this answer)
As each process has its own signal queue, each thread in the process has its own signal queue. But the thread signal queue is the union of its own queue and the process queue; that is how POSIX threads are modeled. And this feature is exploited for inter-thread communication (achieved using pthread_sigmask and sigwait). But that is not the case with python. Python signal handlers are always executed in the main interpreter's main python thread, and only the main thread of the main interpreter is allowed to set a new signal handler.

use of signals with POSIX threads on linux

The signal mask can be set on a per thread basis, but what about signal handles? If I call sigaction() before creating new threads with pthread_create(), will the new threads get the same signal handler? What if I use sigaction() after pthread_create(), will that change the entire process signal handlers or just the ones of the thread?
There is only ONE signal handler per process. So threads are not relevant in any kind here. The signal handler is called in the thread context which receives the signal. Which thread receives the signal is not specified if multiple threads have not blocked the signal.
You have to take care if multiple threads waits in system calls. Also you have to take care with using timer actions and calls to sleep.
You may also find this answer helpful: POSIX threads and signals

Implementation of Signals under Linux and Windows?

I am not new to the use of signals in programming. I mostly work in C/C++ and Python.
But I am interested in knowing how signals are actually implemented in Linux (or Windows).
Does the OS check after each CPU instruction in a signal descriptor table if there are any registered signals left to process? Or is the process manager/scheduler responsible for this?
As signal are asynchronous, is it true that a CPU instruction interrupts before it complete?
The OS definitely does not process each and every instruction. No way. Too slow.
When the CPU encounters a problem (like division by 0, access to a restricted resource or a memory location that's not backed up by physical memory), it generates a special kind of interrupt, called an exception (not to be confused with C++/Java/etc high level language exception abstract).
The OS handles these exceptions. If it's so desired and if it's possible, it can reflect an exception back into the process from which it originated. The so-called Structured Exception Handling (SEH) in Windows is this kind of reflection. C signals should be implemented using the same mechanism.
On the systems I'm familiar with (although I can't see why it should be much different elsewhere), signal delivery is done when the process returns from the kernel to user mode.
Let's consider the one cpu case first. There are three sources of signals:
the process sends a signal to itself
another process sends the signal
an interrupt handler (network, disk, usb, etc) causes a signal to be sent
In all those cases the target process is not running in userland, but in kernel mode. Either through a system call, or through a context switch (since the other process couldn't send a signal unless our target process isn't running), or through an interrupt handler. So signal delivery is a simple matter of checking if there are any signals to be delivered just before returning to userland from kernel mode.
In the multi cpu case if the target process is running on another cpu it's just a matter of sending an interrupt to the cpu it's running on. The interrupt does nothing other than force the other cpu to go into kernel mode and back so that signal processing can be done on the way back.
A process can send signal to another process. process can register its own signal handler to handle the signal. SIGKILL and SIGSTOP are two signals which can not be captured.
When process executes signal handler, it blocks the same signal, That means, when signal handler is in execution, if another same signal arrives, it will not invoke the signal handler [ called blocking the signal], but it makes the note that the signal has arrived [ ie: pending signal]. once the already running signal handler is executed, then the pending signal is handled. If you do not want to run the pending signal, then you can IGNORE the signal.
The problem in the above concept is:
Assume the following:
process A has registered signal handler for SIGUSR1.
1) process A gets signal SIGUSR1, and executes signalhandler()
2) process A gets SIGUSR1,
3) process A gets SIGUSR1,
4) process A gets SIGUSR1,
When step (2) occurs, is it made as 'pending signal'. Ie; it needs to be served.
And when the step (3) occors, it is just ignored as, there is only one bit
available to indicate the pending signal for each available signals.
To avoid such problem, ie: if we dont want to loose the signals, then we can use
real time signals.
2) Signals are executed synchronously,
Eg.,
1) process is executing in the middle of signal handler for SIGUSR1,
2) Now, it gets another signal SIGUSR2,
3) It stops the SIGUSR1, and continues with SIGUSR2,
and once it is done with SIGUSR2, then it continues with SIGUSR1.
3) IMHO, what i remember about checking if there are any signal has arrived to the process is:
1) When context switch happens.
Hope this helps to some extend.

Interrupting syscalls in threads on linux

I have a pthread that runs in a loop, calling accept() in a blocking manner. Is there any way to interrupt that call from another thread? Everything points to sending the thread a signal, but apparently you can only send a process a signal.
I can't just kill the thread because then it leaves the socket open. And that's not very clean anyway. Is there really no way to do this?
You can signal a thread using pthread_kill(3).
The pthread_kill() function sends the signal sig to thread, another
thread in the same process as the caller.
If a signal handler is installed, the handler will be invoked in the
thread thread.
Note, you don't have to kill the thread; you can send a signal that simply makes accept fail with EINTR.
Either use select(), or send the singal to the process (this will be a problem if you just want to interupt one of the threads).

Status of threads when signal handler runs

Assume a multi-threaded application, with a signal handler defined in it.
Now if a signal is delivered to the PROCESS, and signal handler is invoked - My doubt is what happens to other threads during the period signal handler is running. Do they keep running, as if nothing has happened or they are suspended for that period .. or ...?
Also if someone can tell me WHY to justify the answer?
The specification is pretty clear how signals and threads interact:
Signals generated for the process shall be delivered to exactly one of those threads within the process which is in a call to a sigwait() function selecting that signal or has not blocked delivery of the signal.
As the signal is delivered to exactly one thread, other threads are unaffected (and keep running).
The threads are independent: a signal from one thread to a second thread will not affect any of the others. The why is because they are independent. The only reason why it would affect the others is if the signal handler of the thread in question somehow interacts with other threads.

Resources