Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Page 1 of 15
Table of contents
Introduction What are signals? Signal as interrupt Signal masks What signals are good for Signals that report exceptions Other uses of signals Types of signals Handling exception signals SIGKILL and SIGSTOP SIGKILL SIGSTOP Registering signal handler signal() Ignoring signals and restoring original signal handler function sigaction()
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 2 of 15
IntroductionBACK TO TOC
Perhaps any engineer developing for Linux encounters this problem. Whats is the right way to terminate the program? What are the ways to receive notifications from operating system about events that occur. Traditional Unix systems have the answers ready. The answer to these questions is signals. This article addresses these questions. Here, Ill try to explain what signals are, their nature. Well talk about what are the right ways to handle signals, what signals to handle and what are the pitfalls of signal handling in Linux in particular.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 3 of 15
The C library assigns default signal handlers. This means that even if you leave signals untouched, your program will process signals and will respond to them according to default behavior. I will describe default signal behavior a little later in this article.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 4 of 15
SIGQUIT Again, according to documentation, this signal means Quit from keyboard. In reality I couldnt find who sends this signal. I.e. you can only send it explicitly. SIGILL Illegal instruction signal. This is a exception signal, sent to your application by the operating system when it encounters an illegal instruction inside of your program. Something like this may happen when executable file of your program has been corrupted. Another option is when your program loads dynamic library that has been corrupted. Consider this as an exception of a kind, but the one that is very unlikely to happen. SIGABRT Abort signal means you used used abort() API inside of your program. It is yet another method to terminate your program. abort() issues SIGABRT signal which in its term terminates your program (unless handled by your custom handler). It is up to you to decide whether you want to use abort() or not. SIGFPE Floating point exception. This is another exception signal, issued by operating system when your application caused an exception. SIGSEGV This is an exception signal as well. Operating system sends a program this signal when it tries to access memory that does not belong to it. SIGPIPE Broken pipe. As documentation states, this signal sent to your program when you try to write into pipe (another IPC) with no readers on the other side. SIGALRM Alarm signal. Sent to your program using alarm() system call. The alarm() system call is basically a timer that allows you to receive SIGALRM in preconfigured number of seconds. This can be handy, although there are more accurate timer API out there. SIGTERM This signal tells your program to terminate itself. Consider this as a signal to cleanly shut down while SIGKILL is an abnormal termination signal. SIGCHLD Tells you that a child process of your program has stopped or terminated. This is handy when you wish to synchronize your process with a process with its child. SIGUSR1 and SIGUSR2 Finally, SIGUSR1 and SIGUSR2 are two signals that have no predefined meaning and are left for your consideration. You may use these signals to synchronise your program with some other program or to communicate with it.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 5 of 15
SIGKILLBACK TO TOC
SIGKILL, on the contrary to SIGTERM, indicates abnormal termination of the program. You cannot change how your program handles it. It will always terminate your program. However, you can send this signal. SIGKILLs value is 9. This is why kill -9 <pid> shell command is so effective it sends SIGKILL signal to the process.
SIGSTOPBACK TO TOC
SIGSTOP used when debugging. When you debug your program, operating system sends SIGSTOP to stop your program, for instance in case it reaches a breakpoint. Operating system does not let you change its handler because you may cause your program to be undebuggable.
signal()BACK TO TOC
This is the oldest one. It accepts two arguments, first signal number (one of those SIGsomething) and second pointer to a signal handler function. Signal handler function returns void and accepts single integer argument that represents a signal number that has been sent. This way you can use the same signal handler function for several different signals. Here is a short code snippet demonstrating how to use it. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 #include <stdio.h> #include <stdlib.h> #include <signal.h> void sig_handler(int signum) { printf("Received signal %d\n", signum); } int main() { signal(SIGINT, sig_handler); sleep(10); // This is your chance to press CTRL-C return 0; }
This nice and small application registers its own SIGINT signal. Try compiling this small program. See what is happening when you run it and press CTRL-C.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 6 of 15
Although this seems to be everything you may need, it is better to avoid using signal(). Theres a portability problem with this system call. I.e. it behaves differently on different operating systems. Theres a newer system call that does everything signal() does and also gives slightly more information about the actual signal, its origin, etc.
sigaction()BACK TO TOC
sigaction() is another system call that manipulates signal handler. It is much more advanced comparing to good old signal(). Let us take a look at its declaration
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Its first argument specifies a signal number. Second and third arguments are pointers to structure called sigaction. This structure specifies how process should handle given signal. 1 struct sigaction 2 { 3 void (*sa_handler)(int signum); 4 void (*sa_sigaction)(int signum, siginfo_t *siginfo, 5 void *uctx); 6 sigset_t sa_mask; 7 int sa_flags; 8 void (*sa_restorer)(void); 9 }; sa_handler is a pointer to the signal handler routine. The routine accepts single integer number containing signal number that it handles and returns void same as signal handler registered by signal(). In addition, sigaction() let you have more advanced signal handler routine. If needed sa_sigaction pointer should point to the advanced signal handler routine. This one receives much more information about the origin of the signal. To use sa_sigaction routine, make sure to set SA_SIGINFO flag in sa_flags member of struct sigaction. Similarily to sa_handler, sa_sigaction receives an integer telling it what signal has been triggered. In addition it receives a pointer to structure called siginfo_t. It describes the origin of the signal. For instance, si_pid member of siginfo_t holds the process ID of the process that has sent the signal. There are several other fields that tell you lots of useful information about the signal. You can find all the details on sigactions manual page (man sigaction). Last argument received by sa_sigaction handler is a pointer to ucontext_t. This type different from architecture to architecture. My advice to you is to ignore this pointer, unless you are writing a new debugger. One additional advantage of sigaction() compared to signal() is that it allows you to tell operating system what signals can handle signal you are registering. I.e. it gives you full control over what signals can arrive, while your program handling another signal. To tell this, you should manipulate sa_mask member of the struct sigaction. Note that is a sigset_t field. sigset_t type represents signal masks. To manipulate signal masks, use one of the following functions: int sigemptyset(sigset_t *) to clear the mask. int sigfillset(sigset_t *) to set all bits in the mask. int sigaddset(sigset_t *, int signum) to set bit that represents certain signal. int sigdelset(sigset_t *, int signum) to clear bit that represents certain signal. int sigismember(sigset_t *, int signum) to check status of certain signal in a mask.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 7 of 15
struct sigaction act; void sighandler(int signum, siginfo_t *info, void *ptr) { printf("Received signal %d\n", signum); printf("Signal originates from process %lu\n", (unsigned long)info->si_pid); } int main() { printf("I am %lu\n", (unsigned long)getpid()); memset(&act, 0, sizeof(act)); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; sigaction(SIGTERM, &act, NULL); // Waiting for CTRL+C... sleep(100); return 0; }
And this is what happens when we try to run it. First we run the program.
~/works/sigs --> ./a.out I am 18074
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 8 of 15
We can see that it recognized the process that has killed it and printed its process ID.
ConclusionBACK TO TOC
I hope you found this article interesting. If you have questions, dont hesitate to email me to alex@alexonlinux.com. Related posts: 1. SMP affinity and proper interrupt handling in Linux 2. How to handle SIGSEGV, but also generate a core dump Bookmark: digg, del.icio.us, reddit, stumbleupon, technorati, twitter, google, yahoo, facebook Tags: exception, linux, notifications, programming, sigaction, sigkill, signal, thread Comment (RSS) | Trackback Did you know that you can receive periodical updates with the latest articles that I write right into your email box? Alternatively, you subscribe to the RSS feed! Want to know how? Check out Subscribe page
24 Comments
1.
Mark Pettit says: April 30, 2009 at 1:35 pm Your comment on SIGHUP regarding not using controlling terminals is technically not true. From X-windows, opening a session to xterm/aterm/konsole etc opens a controlling terminal. Then, killing or closing such a window wile it was running a program (say vi), would cause SIGHUP to be sent to the program (vi). In fact, if as I do here at my work, I have an ssh session to a Solaris box, and I switch off my laptop or pull the ethernet, eventually the ssh session on the Solaris box will detect that Ive gone and send a SIGHUP to whatever program I was running. Reply Quote
2.
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 9 of 15
@Mark Pettit You are right. Thank you for pointing this out. Ill fix the article. Reply Quote 3. Clayton says: May 28, 2009 at 11:12 pm Alex: Extremely helpful article! Im impressed with the wealth of information on your blog, definitely looking forward to more posts Reply Quote 4. Alexander Sandler says: May 28, 2009 at 11:33 pm @Clayton Thanks for a warm comment. You are most welcome Reply Quote 5. Andre Goddard Rosa says: July 25, 2009 at 6:51 am Thanks for another nice article! Id like to emphasize what youve said stressing that signals are a process-wide resource that must be managed with care, normally on a central place so that it does not gets messed. Important to check if a library that you could probably use depends on some signal to behave, as it could also mess the application state. Also, Id like to say that signal handlers are very restricted environment, with different stack information, and not all functions can be called safely from inside a signal handler. There are many restrictions from calling arbitrary functions from inside a handler. Thanks again! Reply Quote 6. kamal says: September 24, 2009 at 12:14 pm Hi Alex , Thanks for sharing the information. I am implementing one signal handler for three signals (SIGSEGV, SIGILL, SIGBUS ).
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 10 of 15
I want to mask other two signals before entering into the handler(no nesting of signals). and when i return from handler , restore the signal mask usng (sigsetjmp /siglongjmp). and it should be ready to server any of three handler again. file1.c sigsegtjmp( env,1); .. sigemptyset(&sa.sa_mask); <<<< does this right way to do this ? sigaddset(&sset , SIGILL); <<< shd i use sigprocmask ? sigaddset(&sset , SIGSEGV); sigaddset(&sset , SIGBUS); sigaction (); file2.c hanlder () { /* doing my work */ .. sigjongjmp(); .. } Reply Quote 7. kamal says: September 24, 2009 at 12:20 pm I think below code shd work. Please correct if i am wrong sigsetjmp(..); sigfillset(); sigdelset(SIGSEGV); sigdelset(SIGILL); sigdelset(SIGBUS); sigprocmask(SIG_SETMASK,..); sigaction(); and in handler i ll call siglongjmp to restore env . problem is its not working on AIX5.1 , Linux is ok. Reply Quote 8. Alexander Sandler says:
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 11 of 15
September 28, 2009 at 9:07 am @kamal I dont know if what youve suggested will work. However, there is a much easier way of doing the same thing actually it is in the article and careful reader should have seen this Use sigaction() to register signal handlers. When calling sigaction(), one of the things you pass in called sa_mask. This is a signal mask that tells the OS what signals should be blocked when handling the signal youre registering. This is exactly what you need. Reply Quote 9. kamal says: September 29, 2009 at 7:23 am Thanks for reply Alex! I understood the functionality of sigaction + sa_mask. Here my intention is to block some particular set of signals , and once i am done with the handling then jump back and restore ( un block all those handlers ) and get ready to handle signals again. If i will use sigsetjmp/siglongjmp , does signal will be restored ?? I am thought of putting sigsetjmp just above sigaction and corresponding siglongjmp at the end of handler. Reply Quote 10. kamal says: September 29, 2009 at 7:45 am typo : ( un block all those signals** ) Reply Quote 11. Alexander Sandler says: October 14, 2009 at 9:33 am @kamal Ive never used sigsetjmp() and siglongjmp() before so I honestly cannot tell you if these API will do the job for you. According to their man page, you can use them to do that. I am wondering though, why you are reinventing the wheel if operating system/libc already can do it for you using? Reply Quote 12. kamal says: October 14, 2009 at 9:50 am OS will block only that signal for which handler is installed. In case , if i have same handler for three different signals and when any of one those signal will come OS/Libc will block
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 12 of 15
that signal BUT who will re responsible for blocking the other two signals ( I want handle one signal at a time- No nesting ). Thats what i am trying to do here. Cheers!!! Kamal Reply Quote 13. Kevin says: February 4, 2011 at 12:23 am Taking an operating systems class in college now. This tutorial was on the dot with respect to what i needed to learn. Thanks!! Reply Quote 14. Alexander Sandler says: March 2, 2011 at 1:39 am @Kevin I was glad to hear that you found it useful. Please come again (and bring all your student fellows along with you ) Reply Quote 15. Jithu M says: April 12, 2011 at 8:33 am thanx a lot Reply Quote 16. Namekata says: July 1, 2011 at 1:00 am FYI, you can send SIGQUIT with Ctrl-. Reply Quote 17. Rajiv says: September 26, 2011 at 10:48 pm Alex, good info, Just wondering, how to create customized signals Reply Quote 18. Alexander Sandler says: September 29, 2011 at 2:26 pm
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 13 of 15
@Rajiv I am afraid you cant. There are 32 predefined signals. You can use SIGUSR1 and SIGUSR2 for your own purposed, but otherwise youre pretty much stuck with whats already there. Reply Quote 19. bindhi06 says: December 8, 2011 at 2:05 pm Hi Alexander, Thanks for sharing this information. Its really useful. Reply Quote 20. Deepak John Paul says: February 14, 2012 at 1:53 pm Thank you Alex, it was a very helpful blog Reply Quote 21. pavan says: March 27, 2012 at 12:59 pm super alex Reply Quote 22. pavan says: March 27, 2012 at 12:59 pm damal alex Reply Quote 23. pavan says: March 27, 2012 at 1:06 pm Originally Posted By pavandamal alex Reply Quote
Leave a Reply
Name (required) Mail (will not be published) (required) Website
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 14 of 15
Submit Comment
Notify me of followup comments via e-mail Crisis New article Signal Handling in Linux
Search
Categories
Articles Blog Code library Howto News Opinion Other Stuff Programming Articles Resources Reviews Short articles System Administrator Articles
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012
Page 15 of 15
Interesting blogs
CodeBrainz.ca dmiessler.com Evan Jones I geek Insanely Low-Level Ivan Novick's Code Snippets Nick Black Sparc86s Blog tenshu.net
Follow me on Twitter
Deleted all spam posts. My apologies for the inconvenience. 2012/02/28 Oh how lovely. My twitter account was hacked. Please ignore all links coming from my twitter that are not to http://t.co/0O8b97Mu 2012/02/28 http://t.co/ul644Ozj - post about some of the useful gcc macro language extensions. 2012/02/28 UML cheatsheet: http://t.co/q5iHcTYL 2011/09/19 Building a physical CPU load meter http://zite.to/lWTC4j 2011/06/30 LLVM Project Blog: What Every C Programmer Should Know About Undefined Behavior #1/3 http://is.gd/r0eKro 2011/05/23 On TermKit http://zite.to/l7lXRP . Very interesting idea... 2011/05/18 The L Programming Language & System http://zite.to/lonjvp 2011/05/16 Process kills developer passion http://zite.to/mNXisN 2011/05/11 8 Really Useful Ubuntu Unity Quicklists http://zite.to/lX56yI via @Ziteapp 2011/05/09
http://www.alexonlinux.com/signal-handling-in-linux
4/4/2012