The man page for pthreads mentions:
POSIX.1 also requires that threads share a range of other attributes
(i.e., these attributes are process-wide rather than per-thread):
...
- signal dispositions
...
What do "signal dispositions" mean?
I signal disposition is the action a process takes when a signal is delivered. Each signal has a disposition. There are defaults.
From signal(7):
Signal Dispositions
Each signal has a current disposition, which determines how the process
behaves when it is delivered the signal.
[Dispositions are:]
Term Default action is to terminate the process.
Ign Default action is to ignore the signal.
Core Default action is to terminate the process and dump core (see core(5)).
Stop Default action is to stop the process.
Cont Default action is to continue the process if it is currently stopped.
[...]
The signal disposition is a per-process attribute: in a multithreaded
application, the disposition of a particular signal is the same for all
threads.
The disposition of a signal is how it is handled.
It might be ignored
It might be handled using the default response (which depends on the signal)
stop
exit
exit with core dump
ignore
It might be handled by a user-defined signal handler
There can also be issues of signals masked while the signal handler is called, and so on.
This means how Unix process reacts to signals. See signal(7).
Related
Consider a scenario like this: The parent process calls wait() to wait for the child process to exit, and the signal handler is registered for SIGCHLD. When the parent process blocks at wait(), the child process ends, at which point the parent process receives a SIGCHLD signal (regardless of setting special fields).
After I tested, I found that wait() was not interrupted by the SIGCHLD` signal to fail and return -1, but returned successfully after executing the signal processing function. Why is that?
man wait
ERRORS
EINTR: WNOHANG was not set and an unblocked signal or a SIGCHLD was caught
Since you've established a signal handler for SIGCHLD, wait does not get interrupted.
For more info, see: signal, especially:
Waiting for a signal to be caught
Synchronously accepting a signal
Signal mask and pending signals
A signal may be blocked, which means that it will not be
delivered until it is later unblocked. ...
Execution of signal handlers
Interruption of system calls and library functions by signal handlers
If a signal handler is invoked while a system call or library function call is blocked, then either:
the call is automatically restarted after the signal handler returns; or
the call fails with the error EINTR.
Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across UNIX systems; below, the details for Linux.
If a blocked call to one of the following interfaces is
interrupted by a signal handler, then the call is automatically
restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call fails with the error EINTR:
wait
After I tested, I found that wait() was not interrupted by the SIGCHLD` signal to fail and return -1, but returned successfully after executing the signal processing function. Why is that?
Well, if the signal handler ran while the thread was blocked in wait() then that call was interrupted. I guess the question is why wait() then went ahead with collecting the child and returned successfully instead of failing with EINTR.
I can reproduce that behavior. The specifics of how you register the handler are unclear, but in my tests I see the handler running and wait() thereafter returning successfully even when the SA_RESTART flag is not set for SIGCHLD, which is generally a major factor in whether restartable system calls such as wait() fail with EINTR when interrupted by a signal.
I'm having trouble locating any documentation that specifically prescribes the observed combination of results for wait() + handler function + SIGCHLD, but the bottom line is that SIGCHLD is special. In particular, it has a special relationship with wait(), because the events that a system-generated SIGCHLD reports on are exactly the ones that a blocking wait() call is waiting for. Some of the manifestations of that specialness are
The sigaction() function defines two flags modulating behavior related specifically to SIGCHLD, and none specific to any other signal.
Even though the default disposition of SIGCHLD is documented as SIG_IGN, its actual default behavior is unique to that signal and distinct from the behavior obtained by explicitly setting the disposition to SIG_IGN.
POSIX has special provisos for the behavior of the wait-family functions, as described in the notes in the wait() manual page, about how these functions are affected by the disposition and flags associated with SIGCHLD.
I don't think either POSIX or Linux explicitly says so, but it all comes around to a pending SIGCHLD being how the wait-family functions recognize that there is a child to collect. POSIX is sufficiently unspecific that I think other POSIX systems could do it differently, but to the best of my knowledge, using SIGCHLD for this purpose is both traditional and what Linux does. Enough so that signal-handling behavior is specifically designed to accommodate the common behavior of using wait() inside a handler for SIGCHLD to provide for central processing of terminated children.
It is also notable that wait() will collect the child and clear the pending SIGCHLD even if that signal is blocked, analogously to how sigwait() will receive blocked signals. In that case, any registered handler is bypassed.
Your case of establishing a handler for SIGCHLD that does not collect the status information for the child is unusual, but consider what needs to happen here:
a SIGCHLD has been received, it is not blocked, and a signal handler has been registered for it, so the signal handler must run and the SIGCHLD must be removed from the pending list.
after your particular handler runs, the status information for the child has not yet been consumed, so it must be consumed when control returns to wait(). Otherwise, it can never be consumed and reported, for receipt of a SIGCHLD is how the system is triggered to do that, and the context in which the status information is delivered.
I anticipate that your wait() would fail with either ECHILD or EINTR if the signal handler collected the waited-for child via its own wait() call. Which one depends in part on whether the SA_RESTART flag is set for SIGCHLD. I anticipate that it would fail with EINTR if there was a running child, and the wait() was interrupted by a synthetic SIGCHLD, and the SA_RESTART flag was not set.
I am programming a tree of processes in Linux and I wonder if there is any signal that can be used just to send from A process to B process without affecting B process.
For example, assume B_pid is the process B's ID, if process A calls kill(B_pid, SIGSTOP); then A will pause B. What I am looking for is a signal, let's say SIGNOTHING, that when A calls kill(B_pid, SIGNOTHING), then it just simply sends a message to B rather than doing something to both B and the system.
SIGUSR1 and SIGUSR2 are designed for that purpose.
If you invoke the following command on your shell:
kill -l
you get a full list of signals available for your system.
Most of the signals can be used to simply "receive" them on the target side. BUT: Most signals are also used by the system itself to tell the application that something special happened, like SIGSEGV. So it makes no sense to use signals, which have a fixed meaning as they are used to communicate from kernel/OS to the application.
For user signals, you have two signals reserved, which can be used for everything you like: SIGUSR1 and SIGUSR2.
Not all Unix systems have these signals! So first take a look which signals can be used on your current system!
Additional hint:
Check you signal handlers and the context on which they are running. On some implementations it is not allowed to call non-reentrant functions from the context of the handler. So it is maybe more useful to communicate via a pipe or any other IPC method.
There are signals that are meant for use for user programs. From man signal:
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
SIGSTOP will always stop the program and SIGKILL will always terminate the program.
There are two user-defined signals commonly used for signal communication between processes:
SIGUSR1 ... User-defined signal 1
SIGUSR2 ... User-defined signal 2
And there is also a whole range of real-time signals for use as user-defined signals between SIGRTMIN and SIGRTMAX, that have to be at least 8 signals (ie. SIGRTMAX - SIGRTMIN >= 8) and linux supports 33 signals. These are all for use for user-application to do anything it desires.
Basically each signal in Linux has a action associated with it.
Man page of signal:
Signal dispositions
Each signal has a current disposition, which determines how the
process behaves when it is delivered the signal.
The entries in the "Action" column of the table below specify the
default disposition for each signal, as follows:
Term Default action is to terminate the process.
Ign Default action is to ignore the signal.
Core Default action is to terminate the process and dump core (see
core(5)).
Stop Default action is to stop the process.
Cont Default action is to continue the process if it is currently
stopped.
SIGSTOP
SIGSTOP P1990 Stop Stop process
A process can change the disposition of a signal using sigaction(2)
or signal(2). (The latter is less portable when establishing a
signal handler; see signal(2) for details.) Using these system
calls, a process can elect one of the following behaviors to occur on
delivery of the signal: perform the default action; ignore the
signal; or catch the signal with a signal handler, a programmer-
defined function that is automatically invoked when the signal is
delivered.
You can define your own signal handler and define the behavior of your process.
Note: SIGKILL and SIGSTOP cannot be caught
Signal mask is thread-specific, which means blocking a signal doesn't prevent it from being delivered to another thread where this signal isn't blocked. When execution enters into a handler function (assuming no SA_NODEFER) "current" signal becomes blocked.
Does it mean it will be blocked for all threads in current process or it is possible for next such signal to be delivered to another thread (while it is still being handled in first thread)?
Reading man sigaction:
sa_mask specifies a mask of signals which should be blocked (i.e., added to the signal mask of the thread in which the signal handler is invoked) during execution of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.
This sounds like the masking of the currently handled signal only affects the handling thread, so other threads may handle further signals.
I think it is typical for a multithreaded system to block all signals for all threads except one (or several) dedicated signal handling threads (e.g. one that is polling on a signalfd). That way you never have to worry about signals landing on some unpredictable thread.
I'm sending a signal from a module in the kernel space to a process. This process has one thread waiting for the signal.
I read the signal manual and it says:
The signal disposition is a per-process attribute: in a multithreaded application, including the disposition of a signal is the same for all threads.
Thus, and according to the manual pthread_sigmask:
http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
I'm trying to block the signal in the main function of the application by calling:
siginfo_t infoh1;
sigset_t waith1;
sigemptyset(&waith1);
sigaddset(&waith1, SIG_HILO1);
pthread_sigmask( SIG_BLOCK, &waith1, NULL );
Note that the thread is waiting for it in its execution function.
result = sigwaitinfo (&waith1, &infoh1);
The signal is sent, but the thread never receives it (it hangs waiting).
What am I doing wrong? I tested with different codes from different websites without success.
I use signals a lot in my *nix code and I don't think this is a good approach.
I recommend that all threads are set to ignore signals. The main process handles the signal while the thread sits on a mutex/condition. On signal the main process sets a global static flag with the signal type and then notifies the thread which duly checks the flag to see which signal was caught.
It's a safe and easy solution.
In Linux 2.6, I would like my process to catch both SIGHUP and SIGTERM in order to exit orderly.
When the node shuts down, logs show that it will handle either SIGHUP (the parent process receives SIGTERM) or SIGTERM first.
My question is: is there a possibility that the handlers for these signals are called concurrently? or the kernel triggers one after the other?
Depending on your code architecture you could enforce synchronous reading of signals preventing any concurrency issues. You could use signalfd and then read from that fd whenever you want to check on any outstanding signals. If you need them to behave in their asynchronous default with a signal handler I think you have to be prepared for your signal handler to be potentially interrupted.
man signalfd
In Asynchronous signals to a process, the Linux kernel send signals with a system call to target process structure and when context of the process is switched to RUN state, signals are handled by root thread and block signals on all other threads. Since the stack space is different for each thread each signal can be handled at a time(Correct if am wrong).