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.

#endif<br />

}<br />

static int signal_was_caught(void)<br />

{<br />

if (sigint_received) printf("SIGINT received!\n");<br />

if (sigterm_received) printf("SIGTERM received!\n");<br />

if (sigquit_received) printf("SIGQUIT received!\n");<br />

return (sigint_received || sigterm_received || sigquit_received);<br />

}<br />

int main(int argc, char *argv[ ]) {<br />

char buffer[80];<br />

setup_signal_handler(SIGINT, handle_sigint);<br />

setup_signal_handler(SIGTERM, handle_sigterm);<br />

setup_signal_handler(SIGQUIT, handle_sigquit);<br />

/* The main loop of this program simply reads input from stdin, and<br />

* throws it away. It's useless functionality, but the point is to<br />

* illustrate signal handling, and fread is a system call that will<br />

* be interrupted by signals, so it works well for example purposes<br />

*/<br />

while (!feof(stdin)) {<br />

fread(buffer, 1, sizeof(buffer), stdin);<br />

if (signal_was_caught( )) break;<br />

}<br />

return (sigint_received || sigterm_received || sigquit_received);<br />

}<br />

This code clearly illustrates both points made in the “Solution” section. Separate signal<br />

handlers are used for each signal that we want to handle: SIGINT, SIGTERM, and<br />

SIGQUIT. For each signal handler, a global flag is set to nonzero to indicate that the<br />

signal was caught. Later, when the system call—fread( ) in this case—returns, the<br />

flags are checked and fully handled. (It is true that fread( ) itself is not really a system<br />

call, but it is a wrapper around the read( ) system call.)<br />

In the function setup_signal_handler( ), weusesigaction( ) to set up our signal<br />

handlers, rather than signal( ), if it is available. On most modern Unix systems,<br />

sigaction( ) is available and should be used. One problem with signal( ) is that on<br />

some platforms it is subject to race conditions because it is implemented as a wrapper<br />

around sigaction( ). Another problem is that on some systems—most notably<br />

those that are BSD-derived—some system calls are restarted when interrupted by a<br />

signal, which is typically not the behavior we want. In this particular example, it certainly<br />

is not because we won’t get the opportunity to check our flags until after the<br />

call to fread( ) completes, which could be a long time. Using sigaction( ) without<br />

the nonportable SA_RESTART flag will disable this behavior and cause fread( ) to<br />

return immediately with the global errno set to EINTR.<br />

Performing Proper Signal Handling | 715<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!