21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Do not share signal handlers.<br />

Several signals are normally used to terminate a program, including SIGTERM,<br />

SIGQUIT, and SIGINT (to name but a few). It is far too common to see code like<br />

this:<br />

signal(SIGINT, signal_handler);<br />

signal(SIGTERM, signal_handler);<br />

signal(SIGQUIT, signal_handler);<br />

Such code is unsafe because while signal_handler( ) is handling a SIGTERM that<br />

has been delivered to the process, a SIGINT could be delivered to the same function.<br />

Most programmers have a tendency to write their signal handlers in a nonreentrant<br />

fashion because the same signal will not be delivered to the process<br />

again until the first handler returns. In addition, many programmers write their<br />

code under the false assumption that no signals can be delivered while a signal<br />

handler is running, which is not true.<br />

Do as little work as is possible in a signal handler.<br />

Only a small number of system functions are safe to call from a signal handler.<br />

Worse, the list is different on different operating systems. Worse still, many<br />

operating systems do not document which functions are safe, and which are not.<br />

In general, it is a good idea to set a flag in a signal handler, and do nothing else.<br />

Never make calls to dynamic memory allocation functions such as malloc( ) or<br />

free( ), or any other functions that may make calls to those functions. This<br />

includes calls to functions like syslog( )—which we’ll discuss in more detail<br />

later in this chapter (see Recipe 13.11)—for a variety of reasons, including the<br />

fact that it often makes calls to malloc( ) internally.<br />

Note that on many systems, system functions like malloc( ) and free( ) are reentrant,<br />

and can be called safely from multiple threads, but this type of reentrancy<br />

is not the same as what is required for use by a signal handler! For thread<br />

safety, these functions usually use a mutex to protect themselves. But what happens<br />

if a signal is delivered to a thread while that thread is in the process of running<br />

malloc( )? The simple answer is that the behavior is undefined. On some<br />

systems, this might cause a deadlock because the same thread is trying to acquire<br />

the same mutex more than once. On other systems, the acquisition of the mutex<br />

may fail, and malloc( ) proceeds normally, resulting in a double release of the<br />

mutex. On still other systems, there could be no multithreaded protection at all,<br />

and the heap could become corrupted. Many other possibilities exist as well, but<br />

these three alone should scare you enough to make the point.<br />

If you must perform more complex operations in a signal handler than we are recommending<br />

here, you should block signal delivery during any nonatomic operations<br />

that may be impacted by operations performed in a signal handler. In addition, you<br />

should block signal delivery inside all signal handlers.<br />

Performing Proper Signal Handling | 713<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!