Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most important signals to handle?

Recently I was working on a software written in c which had about a 3-4 thousand lines of code.When I started to get segmentation faults ,I added a SIGSEGV handler.This helped me in pin pointing the error as the handler was made to give a backtrace.

My question is apart from SIGSEGV what are the important signals that should be handled when we have a big software, such that error detection will be easy.

This can optionally be used in preventing an attack. Ex The software receiving abort signal when it is doing critical updates/operation.The standard tells that SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGTERM and some more signals have the default property to terminate the process to which this signal is delivered.

So to add another layer of protection to my software will I have to change the behavior of these signals.By protection I mean that I don't want my software to terminate when it is in between a crtical update, I will decide on when to abort.

EDIT:I Want to know how well designed software,handle SIGNAL ,use them like a safety net, which helps as the software is built along.

like image 662
Deepthought Avatar asked Jul 23 '12 18:07

Deepthought


1 Answers

Well, you aren't 100% clear on what you expect from an answer but I'll try to cover the general idea.

First of all, what you could call a 'debugging' signals are (and when to expect them):

  1. SIGILL, SIGFPE — if program tries to run an illegal instruction, usually can appear with wrong CFLAGS and/or own assembly (or serious random breakages);
  2. SIGABRT — caused by the abort() call, for example in assert(). It can also come from libraries, so you usually should handle it;
  3. SIGSEGV — invalid memory access, you probably know all about it already;
  4. SIGBUS — can happen when doing I/O with mmap() and trying to read/write unaccessible memory; it also happened to me when mmap()-based I/O ran out-of-space;
  5. SIGPIPE — when doing I/O on pipes, and the pipe gets disconnected from the other side;
  6. POSIX also specifies SIGSYS for invalid system calls and you probably want to catch that as well (though I never managed to see one).

I would say you need to handle those signals if you are using the relevant operations. They're all in POSIX but I'm not sure if all systems implement them so you may want to use #ifdefs for them anyway (SIG* are guaranteed to be macros and thus suitable for #ifdef).

Other signals you may encounter through the runtime of your program are:

  1. SIGALRM — when using alarm(),
  2. SIGPOLL — when using polling,
  3. SIGCHLD — when spawning processes…

And these are basically signals which you are handling anyway when using the relevant operations and though they terminate by default, you should have other handlers for them anyway.

And finally, if you expect to handle signals sent by user, that's a harsh case — because user can practically send every signal. Thus, if you want to handle it all gracefully, you need to catch every signal from man signal which defaults to termination or abort actions.

If you want to just catch a common subset of signals which you could expect, these would be:

  1. SIGHUP when the terminal with the program (or some other parent if relevant) dies,
  2. SIGINT for ^c key,
  3. SIGQUIT for ^\ key,
  4. SIGTERM for the termination request (sent by the kill program by default and other similar tools),
  5. SIGUSR1 and SIGUSR2 are user-defined signals and usually are used to perform program-specific actions. They are sent by user, and — for some reason — default to killing the program.

There's also SIGKILL but the standard doesn't allow catching it.

I hope I covered the most important signals. Note that I'm a Linux user, and other *nixes may have a few specific signals you also may want to catch.

It usually all depends on what you want to achieve. Although preventing the software from being interrupted by random signals is a good idea, it's usually not worth it to prevent it from being killed by all of them, and especially those which are only sent directly by user.

If user wants to kill the app, he can achieve it anyway, and it should be enough to just handle the common ones — SIGINT and SIGTERM. I would personally expect SIGQUIT (^\ key) to kill the application without letting it finish even critical tasks (like SIGKILL does).

Edit. And as a rationale for the last sentence, think about the following: I've just made something stupid, like removed some important data. Or simply noticed there's something wrong with the cleanup-on-exit procedure. I really want to terminate the program ensuring my signal won't be caught but cause it to return immediately. Even if it would result in broken data, sometimes I would really prefer to have broken data (hoping I would be able to recover what I need) than no data.

like image 111
Michał Górny Avatar answered Oct 17 '22 06:10

Michał Górny