|Applying C - Signals|
|Monday, 09 March 2020|
Page 3 of 3
Signals are most often thought of as software interrupts that indicate some sort of error has occurred. In fact, any process can use a signal to communicate with another process. It is a matter of opinion how useful this is, but it does have the advantage of being simple.
There are a number of functions which can be used to send a signal to a process.
works in the same way as the kill command. You specify the PID number of the process you want to send the signal sig to. If you specify 0 then the signal is sent to every process in the same group as the calling process. If you set it to -1 then the signal is sent to every process that the calling process has permission to send it to. Any other negative PID sends the signal to the process group with that ID. A simpler way of doing this is to use the function:
which sends sig the process group pgrp. If pgrp is 0 then sig is sent to the calling process’s group. Notice you can set the process group of any process you create using C functions or the command line.
Finally, if sig is 0 then no signal is sent, but error checking is performed as if it had been. You can use this to check that a process, or process group, exists. To send a signal, the sender either has to be running as root or as the same user as the receiving process.
is the same as:
i.e. it sends the signal to the calling program.
will send the signal to the process specified by pid and value will be stored in the sig_value field of the siginfo_t struct.
You can send a signal directly to a thread using:
This interrupts the specified thread and performs the action common to all the threads.
Waiting for Signals
There are two functions which cause a process to suspend until a signal occurs. The simplest is:
and it just pauses the process or thread until a handled or unhandled signal occurs. Slightly more sophisticated is:
which does the same thing as pause, but it sets the signal mask for the duration of the suspension. This means you can use mask to temporarily change what signals are allowed.
Notice that pause and sigsuspend cause a handler to be call asynchronously and the program only continues if the handler returns.
You can also wait for a signal without the help of a handler function.
The process simply waits for the signal and continues when the signal happens i.e. a synchronous signal processing. Another way to think of this is that the process blocks until the signal occurs.
There are three functions that perform a synchronous wait:
sigwait(&mask, &sig); sigwaitinfo(&mask, &info); sigtimedwait(&mask, &info, &timeout);
They work in more or less the same way. The mask determines which signals are waited for. For sigwait all that is returned when the signal occurs is its signal number. For sigwaitinfo and sigtimedwait you get a complete siginfo_t struct containing all the information about the signal and sigtimedwait also specifies a timeout via the timespec struct.
There is one subtle point that isn't made very clear in the documentation. The signal that you are waiting for has to be blocked in the calling program and all threads. If it isn't then the result is undefined behavior which in practice generally means that you get default behavior or a handler called.
In chapter but not included in this extract.
Now available as a paperback or ebook from Amazon.
Applying C For The IoT With Linux
Also see the companion book: Fundamental C
or email your comment to: firstname.lastname@example.org
|Last Updated ( Monday, 09 March 2020 )|