|Applying C - Signals|
|Monday, 09 March 2020|
Page 1 of 3
Signals are just software interrupts but this is just the start of the story.This extract is from my book on using C in an IoT context.
Now available as a paperback or ebook from Amazon.
Applying C For The IoT With Linux
Also see the companion book: Fundamental C
Signals are the POSIX way of implementing software interrupts. They are used to inform user-space programs that something has happened and they are also used to terminate a program. Going beyond this they can be generated by user-mode programs to signal to other programs. That is, they can be used as a simple form of inter-process communication (IPC). A signal causes the user program to abandon its normal execution and transfers control to another location. This can be thought of as an exception. There is no exception handling defined within the C language. C has no try-catch type of construct, but there is a standard facility for implementing the same sort of behavior - the longjmp - which deserves to be better known.
There are a number of system-generated signals, which are mostly the result of hardware interrupts that occur in the kernel, which are converted into signals and delivered to the user-mode program that caused them.
There are a many different signals and variations on the standards. The table below list the most commonly encountered.
The Action column indicates the default action performed in response to the signal. There are four possibilities:
Term = terminate process
Core = terminate and perform a core dump
Stop = stop process
Cont = continue process if stopped
While these actions are the default behaviors, a process can block a signal, ignore a signal, or handle it with a custom function. A signal that is set to be ignored is lost, but a signal that is blocked remains pending until it is unblocked. If a signal occurs again while it is blocked, only a single instance of the signal is retained.
For obvious reasons
Notice that there are multiple ways terminate a program.
There are two ways to issue a terminate signal to a running process using the
There are two ways to terminate the foreground process using the terminal.
Finally, it is worth taking note of the way
Dealing with Async
It is important that you realize that signals occur asynchronously. Your program can be interrupted at any time by a signal. If you have a handler set then, unless you take steps to block signals, it too can be interrupted. When a handler returns, your program restarts from where it was. The exception to this is if your program was in the middle of a
All of this means that, even if you are writing a single-threaded program, if you are using signals you have to take account of possible race conditions, which action will be carried out first, and asynchronous execution. For example, if you have a global variable that is used by both your program and a signal handler, then you have the same problems that you would have if you were sharing the variable between two threads. If the program is in the middle of updating the shared variable and a signal interrupts it, then its state is not certain and when the handler updates it and returns, the result is probably not what you expected. The situation is even worse if the handler itself can be interrupted by another signal. To stop this happening always block signals within a handler.
Sharing resources between the program and a signal handler is the same as sharing resources between threads, see Chapter 12.
If you don't make use of a handler for any signal, then you can mostly ignore this problem as by default signals bring the process to an end and all you need to worry about is the state of any open resources that you don't get a chance to gracefully close.
You can also ignore the problem if you choose to handle signals using one of the synchronous approaches. In this case, your program isn't interrupted as it simply either waits for a signal or polls to see if there is a signal to process.
|Last Updated ( Monday, 09 March 2020 )|