--- created_at: '2016-01-17T12:29:15.000Z' title: All about Linux signals (2009) url: http://www.linuxprogrammingblog.com/all-about-linux-signals?page=show author: ingve points: 124 story_text: comment_text: num_comments: 8 story_id: story_title: story_url: parent_id: created_at_i: 1453033755 _tags: - story - author_ingve - story_10919277 objectID: '10919277' year: 2009 --- [Source](http://www.linuxprogrammingblog.com/all-about-linux-signals?page=show "Permalink to All about Linux signals | Linux Programming Blog") # All about Linux signals | Linux Programming Blog [Jump to Navigation][1] ![Home][2] ** [Linux Programming Blog][3] ** const char s[] = "Linux Programming Blog"; ## Main menu * [About][4] [Home][5] › [Blogs][6] › [daper's blog][7] › # All about Linux signals Submitted by daper on Tue, 02/03/2009 - 00:33 * [C][8] * [Linux Programming][9] In most cases if you want to handle a signal in your application you write a simple signal handler like: `void handler (int sig)` and use the [signal(2)][10] system function to run it when a signal is delivered to the process. This is the simplest case, but signals are more interesting than that! Information contained in this article is useful for example when you are writing a daemon and must handle interrupting your program properly without interrupting the current operation or the whole program. # What is covered here The article describes how signals work in Linux and how to handle signals using POSIX API. I will cover functions working on every modern Linux system, but it should also apply to most POSIX systems unless explicitly stated otherwise. Legacy functions are not covered. A basic knowledge about signals is required. # What is signaled in Linux Your process may receive a signal when: * From user space from some other process when someone calls a function like [kill(2)][11]. * When you send the signal from the process itself using a function like [abort(3)][12]. * When a child process exits the operating system sends the `SIGCHLD` signal. * When the parent process dies or hangup is detected on the controlling terminal `SIGHUP` is sent. * When user interrupts program from the keyboard `SIGINT` is sent. * When the program behaves incorrectly one of `SIGILL, SIGFPE, SIGSEGV` is delivered. * When a program accesses memory that is mapped using [mmap(2)][13] but is not available (for example when the file was truncated by another process) - really nasty situation when using mmap() to access files. There is no good way to handle this case. * When a profiler like gprof is used the program occasionally receives `SIGPROF`. This is sometimes problematic when you forgot to handle interrupting system functions like [read(2)][14] properly (`errno == EINTR`). * When you use the [write(2)][15] or similar data sending functions and there is nobody to receive your data `SIGPIPE` is delivered. This is a very common case and you must remember that those functions may not only exit with error and setting the errno variable but also cause the `SIGPIPE` to be delivered to the program. An example is the case when you write to the standard output and the user uses the pipeline sequence to redirect your output to another program. If the program exits while you are trying to send data `SIGPIPE` is sent to your process. A signal is used in addition to the normal function return with error because this event is asynchronous and you can't actually tell how much data has been successfully sent. This can also happen when you are sending data to a socket. This is because data are buffered and/or send over a wire so are not delivered to the target immediately and the OS can realize that can't be delivered after the sending function exits. For a complete list of signals see the [signal(7)][16] manual page. # Signal handlers ## Traditional signal() is deprecated The [signal(2)][10] function is the oldest and simplest way to install a signal handler but it's deprecated. There are few reasons and most important is that the original Unix implementation would reset the signal handler to it's default value after signal is received. If you need to handle every signal delivered to your program separately like handling `SIGCHLD` to catch a dying process there is a race here. To do so you would need to set to signal handler again in the signal handler itself and another signal may arrive before you cal the [signal(2)][10] function. This behavior varies across different systems. Moreover, it lacks features present in [sigaction(2)][17] you will sometimes need. ## The recommended way of setting signal actions: sigaction The [sigaction(2)][17] function is a better way to set the signal action. It has the prototype: 1. int sigaction (int signum, const struct sigaction *act, struct sigaction *oldact); As you can see you don't pass the pointer to the signal handler directly, but instead a `struct sigaction` object. It's defined as: 1. struct sigaction { 2. void (*sa_handler)(int); 3. void (*sa_sigaction)(int, siginfo_t *, void *); 4. sigset_t sa_mask; 5. int sa_flags; 6. void (*sa_restorer)(void); 7. }; For a detailed description of this structure's fields see the [sigaction(2)][17] manual page. Most important fields are: * `sa_handler` \- This is the pointer to your handler function that has the same prototype as a handler for [signal(2)][10]. * `sa_sigaction` \- This is an alternative way to run the signal handler. It has two additional arguments beside the signal number where the `siginfo_t *` is the more interesting. It provides more information about the received signal, I will describe it later. * `sa_mask` allows you to explicitly set signals that are blocked during the execution of the handler. In addition if you don't use the `SA_NODEFER` flag the signal which triggered will be also blocked. * `sa_flags` allow to modify the behavior of the signal handling process. For the detailed description of this field, see the manual page. To use the `sa_sigaction` handler you must use `SA_SIGINFO` flag here. What is the difference between [signal(2)][10] and [sigaction(2)][17] if you don't use any additional feature the later one provides? The answer is: portability and no race conditions. The issue with resetting the signal handler after it's called doesn't affect [sigaction(2)][17], because the default behavior is not to reset the handler and blocking the signal during it's execution. So there is no race and this behavior is documented in the POSIX specification. Another difference is that with [signal(2)][10] some system calls are automatically restarted and with [sigaction(2)][17] they're not by default. ### Example use of sigaction() See [example of using sigaction()][18] to set a signal handler with additional parameters. In this example we use the three arguments version of signal handler for `SIGTERM`. Without setting the `SA_SIGINFO` flag we would use a traditional one argument version of the handler and pass the pointer to it by the `sa_handler` field. It would be a replacement for [signal(2)][10]. You can try to run it and do kill PID to see what happens. In the signal handler we read two fields from the `siginfo_t *siginfo` parameter to read the sender's PID and UID. This structure has more fields, I'll describe them later. The [sleep(3)][19] function is used in a loop because it's interrupted when the signal arrives and must be called again. ### SA_SIGINFO handler In the previous example `SA_SIGINFO` is used to pass more information to the signal handler as arguments. We've seen that the `siginfo_t` structure contains `si_pid` and `si_uid` fields (PID and UID of the process that sends the signal), but there are many more. They are all described in [sigaction(2)][17] manual page. On Linux only `si_signo` (signal number) and `si_code` (signal code) are available for all signals. Presence of other fields depends on the signal type. Some other fields are: * `si_code` \- Reason why the signal was sent. It may be `SI_USER` if it was delivered due to [kill(2)][11] or [raise(3)][20], `SI_KERNEL` if kernel sent it and few more. For some signals there are special values like `ILL_ILLADR` telling you that `SIGILL` was sent due to illegal addressing mode. * For `SIGCHLD` fields `si_status, si_utime, si_stime` are filled and contain information about the exit status or the signal of the dying process, user and system time consumed. * In case of `SIGILL, SIGFPE, SIGSEGV, SIGBUS` `si_addr` contains the memory address that caused the fault. We'll see more examples of use of `siginfo_t` later. ## Compiler optimization and data in signal handler Let's see the following example: 1. #include 2. #include 3. #include 4. #include 5.   6. static int exit_flag = 0; 7.   8. static void hdl (int sig) 9. { 10. exit_flag = 1; 11. } 12.   13. int main (int argc, char *argv[]) 14. { 15. struct sigaction act; 16.   17. memset (&act, ' [1]: http://www.linuxprogrammingblog.com#main-menu [2]: http://www.linuxprogrammingblog.com/sites/linuxprogrammingblog.com/files/logo.png [3]: http://www.linuxprogrammingblog.com/ "Home" [4]: http://www.linuxprogrammingblog.com/about "About this blog" [5]: http://www.linuxprogrammingblog.com/ [6]: http://www.linuxprogrammingblog.com/blog [7]: http://www.linuxprogrammingblog.com/blog/1 [8]: http://www.linuxprogrammingblog.com/c-language "" [9]: http://www.linuxprogrammingblog.com/linux "" [10]: http://www.kernel.org/doc/man-pages/online/pages/man2/signal.2.html [11]: http://www.kernel.org/doc/man-pages/online/pages/man2/kill.2.html [12]: http://www.kernel.org/doc/man-pages/online/pages/man3/abort.3.html [13]: http://www.kernel.org/doc/man-pages/online/pages/man2/mmap.2.html [14]: http://www.kernel.org/doc/man-pages/online/pages/man2/read.2.html [15]: http://www.kernel.org/doc/man-pages/online/pages/man2/write.2.html [16]: http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html [17]: http://www.kernel.org/doc/man-pages/online/pages/man2/sigaction.2.html [18]: http://www.linuxprogrammingblog.com/code-examples/sigaction [19]: http://www.kernel.org/doc/man-pages/online/pages/man3/sleep.3.html [20]: http://www.kernel.org/doc/man-pages/online/pages/man3/raise.3.html