Sei sulla pagina 1di 15

Signal handling in Linux - Alex on Linux

Page 1 of 15

Home Hall of fame Subscribe Contact About

Signal handling in Linux


Posted on April 19, 2009, 8:16 pm, by Alexander Sandler, under Programming Articles.
Download Google Chrome www.Google.com/Chrome Searching is fast and easy with Google's web browser. New Free Software Download Shopping.Indiatimes.com Buy Pen Drives, Music CD's, Mobiles Gifts, Apparels, Watches and more! Linux Iscsi www.Dell.com/Compellent With Fluid Data Storage Technology For Data Center. Know More. Visit! Small Business Management www.sohoos.com Get your free and friendly business management solution for free.

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

Signal handling in Linux - Alex on Linux

Page 2 of 15

sigaction() in action Conclusion

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.

What are signals?BACK TO TOC


Signal is a notification, a message sent by either operating system or some application to your program (or one of its threads). Each signal identified by a number, from 1 to 31. Signals dont carry any argument and their names are mostly self explanatory. For instance SIGKILL or signal number 9 tells the program that someone tries to kill it.

Signal as interruptBACK TO TOC


In addition to informative nature of signals, they also interrupt your program. I.e to handle a signal, one of the threads in your program, stops its execution and temporarily switches to signal handler. Note that as in version 2.6 of Linux kernel, most of the signals interrupt only one thread and not the entire application as it used to be once. Moreover, signal handler itself can be interrupted by some other signal.

Signal masksBACK TO TOC


Each one of signals can be in one of three states: We may have our own signal handler for the signal. Signal may be handled by the default handler. Every signal has its default handler function. For instance, SIGINT default handler will terminate your application. Signal may be ignored. Ignoring signal sometimes referred to as blocking signal. When manipulating signals and managing signal configuration, it is often easier to manage a so called signal mask. It is a bit-mask, where each bit has a corresponding signal. There are 32 (actually 31, 0 doesnt count) different signals, thus we can use single 32-bit integer (unsigned int) to keep information about 32 signals. This is exactly what operating system does. Moreover, signal masks used as arguments in different system calls, thus we will have to work with signal masks.

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

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.

What signals are good forBACK TO TOC


Signals, as their name implies, used to signal something. There are several types of signals, each indicating something of its own. For instance SIGINT that I already mentioned, tells your program that someone tries to interrupt it with CTRL-C. Dedication of each signal is a matter of semantics. I.e. you may want to decide what action shall be associated with each one of the signals. You may decide that some signal will cause your program to print something or draw something on the screen. It is up to you, most of the time. However, there is a common convention of what each and every signal should do. According to this common convention SIGINT expected to cause your program to terminate itself. This is the default response for SIGINT signal and it is in your interest to keep it this way. It is a question of usability. No one wants a program that cannot be interrupted.

Signals that report exceptionsBACK TO TOC


Another way of using signals is to indicate that that something bad have happened. For instance when your program causes a segmentation fault, operating system sends SIGSEGV signal to your application.

Other uses of signalsBACK TO TOC


Signals have several different usages. For instance debuggers rely on signals to receive events about programs that being debugged (read more about this in my article How Debugger Works). Signals is one of so called IPC Inter Process Communication mechanisms. IPC used to, as the abbreviation implies, to allow processes communicate with one another. Another common use is when user wishes that our program will reinitialize itself, but not terminate. In this case, user can send our program a signal from the terminal, using a program called kill. You may be already familiar with this program. It used to kill processes. The truth is that it sends a signal. Each signal has a number that identifies it. By default it sends signal 15, SIGTERM, but it can send just any signal. Lets see most common and their use.

Types of signalsBACK TO TOC


SIGHUP This signal indicates that someone has killed the controlling terminal. For instance, lets say our program runs in xterm or in gnome-terminal. When someone kills the terminal program, without killing applications running inside of terminal window, operating system sends SIGHUP to the program. Default handler for this signal will terminate your program. Thanks to Mark Pettit for the tip. SIGINT This is the signal that being sent to your application when it is running in a foreground in a terminal and someone presses CTRL-C. Default handler of this signal will quietly terminate your program.

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

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.

Handling exception signalsBACK TO TOC


In general I think it would be a good advice to avoid changing signal handler for these signals. Default signal handler for these signals generates core file. Later, you can use core file to analyze the problem and perhaps find a solution. Overwriting signal handler for one of the exception signals, will cause your program to ignore this signal and an exception that has caused the signal. This is something that you dont want to do. In case you still want to handle exception signals, read my How to handle SIGSEGV, but also generate a core dump article.

SIGKILL and SIGSTOPBACK TO TOC


These two signals are special. You cannot change how your program handles these two.

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

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.

Registering signal handlerBACK TO TOC


There are several interfaces that allow you to register your own signal handler.

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.

Ignoring signals and restoring original signal handler functionBACK TO TOC


Using signal() you can set default signal handler for certain signal to be used. You can also tell the system that you would like to ignore certain signal. To ignore the signal, specify SIG_IGN as a signal handler. To restore default signal handler, specify SIG_DFL as signal handler.

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

Page 7 of 15

sigaction() in actionBACK TO TOC


To conclude, I would like to show a small program that demonstrates sigaction() in use. I would like the program to register signal handler for SIGTERM and then, when it receives the signal, print some information about the origin of the signal. On the other hand, I will use Python interpretor to send the program a signal. Here is a program. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include #include #include #include <stdio.h> <signal.h> <string.h> <unistd.h>

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

While it sleeps I ran Python shell and killed it.


~ --> python Python 2.5.2 (r252:60911, Jul 31 2008, 17:31:22) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> import signal >>> print os.getpid() 18075

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

Page 8 of 15

>>> os.kill(18074, signal.SIGTERM) >>>

Heres the rest of the output of the program.


~/lab/sigs --> ./a.out I am 18074 Received signal 15 Signal originates from process 18075 ~/lab/sigs -->

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.

Alexander Sandler says: April 30, 2009 at 3:08 pm

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

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

Signal handling in Linux - Alex on Linux

Page 14 of 15

Submit Comment

Notify me of followup comments via e-mail Crisis New article Signal Handling in Linux
Search

Subscribe Now email or RSS


more info

Most popular posts


tcpdump for Dummies How inheritance, encapsulation and polymorphism work in C++ Multithreaded simple data type access and atomic variables Pythons optparse for human beings Reverse SSH tunnel or connecting to computer behind NAT router C/C++ reference counting with atomic variables and gcc SMP affinity and proper interrupt handling in Linux pthread mutex vs pthread spinlock Signal handling in Linux How debugger works

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

Signal handling in Linux - Alex on Linux

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

2007-2010 Alex on Linux. All rights reserved

http://www.alexonlinux.com/signal-handling-in-linux

4/4/2012

Potrebbero piacerti anche