📄 library_21.html
字号:
Setting this flag for a signal other than <CODE>SIGCHLD</CODE> has no effect.<P><A NAME="IDX1556"></A><U>Macro:</U> int <B>SA_ONSTACK</B><P>If this flag is set for a particular signal number, the system uses thesignal stack when delivering that kind of signal. See section <A HREF="library_21.html#SEC380" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC380">BSD Signal Handling</A>.<P><A NAME="IDX1557"></A><U>Macro:</U> int <B>SA_RESTART</B><P>This flag controls what happens when a signal is delivered duringcertain primitives (such as <CODE>open</CODE>, <CODE>read</CODE> or <CODE>write</CODE>),and the signal handler returns normally. There are two alternatives:the library function can resume, or it can return failure with errorcode <CODE>EINTR</CODE>.<P>The choice is controlled by the <CODE>SA_RESTART</CODE> flag for theparticular kind of signal that was delivered. If the flag is set,returning from a handler resumes the library function. If the flag isclear, returning from a handler makes the function fail.See section <A HREF="library_21.html#SEC362" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC362">Primitives Interrupted by Signals</A>.<P><A NAME="IDX1558"></A><H3><A NAME="SEC350" HREF="library_toc.html#SEC350" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC350">Initial Signal Actions</A></H3><P>When a new process is created (see section <A HREF="library_23.html#SEC405" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_23.html#SEC405">Creating a Process</A>), it inheritshandling of signals from its parent process. However, when you load anew process image using the <CODE>exec</CODE> function (see section <A HREF="library_23.html#SEC406" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_23.html#SEC406">Executing a File</A>), any signals that you've defined your own handlers for revert totheir <CODE>SIG_DFL</CODE> handling. (If you think about it a little, thismakes sense; the handler functions from the old program are specific tothat program, and aren't even present in the address space of the newprogram image.) Of course, the new program can establish its ownhandlers.<P>When a program is run by a shell, the shell normally sets the initialactions for the child process to <CODE>SIG_DFL</CODE> or <CODE>SIG_IGN</CODE>, asappropriate. It's a good idea to check to make sure that the shell hasnot set up an initial action of <CODE>SIG_IGN</CODE> before you establish yourown signal handlers.<P>Here is an example of how to establish a handler for <CODE>SIGHUP</CODE>, butnot if <CODE>SIGHUP</CODE> is currently ignored:<P><PRE>...struct sigaction temp;sigaction (SIGHUP, NULL, &temp);if (temp.sa_handler != SIG_IGN) { temp.sa_handler = handle_sighup; sigemptyset (&temp.sa_mask); sigaction (SIGHUP, &temp, NULL); }</PRE><P><A NAME="IDX1559"></A><H2><A NAME="SEC351" HREF="library_toc.html#SEC351" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC351">Defining Signal Handlers</A></H2><P>This section describes how to write a signal handler function that canbe established with the <CODE>signal</CODE> or <CODE>sigaction</CODE> functions.<P>A signal handler is just a function that you compile together with therest of the program. Instead of directly invoking the function, you use<CODE>signal</CODE> or <CODE>sigaction</CODE> to tell the operating system to callit when a signal arrives. This is known as <DFN>establishing</DFN> thehandler. See section <A HREF="library_21.html#SEC344" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC344">Specifying Signal Actions</A>.<P>There are two basic strategies you can use in signal handler functions:<P><UL><LI>You can have the handler function note that the signal arrived bytweaking some global data structures, and then return normally.<P><LI>You can have the handler function terminate the program or transfercontrol to a point where it can recover from the situation that causedthe signal.</UL><P>You need to take special care in writing handler functions because theycan be called asynchronously. That is, a handler might be called at anypoint in the program, unpredictably. If two signals arrive during avery short interval, one handler can run within another. This sectiondescribes what your handler should do, and what you should avoid.<P><H3><A NAME="SEC352" HREF="library_toc.html#SEC352" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC352">Signal Handlers That Return</A></H3><P>Handlers which return normally are usually used for signals such as<CODE>SIGALRM</CODE> and the I/O and interprocess communication signals. Buta handler for <CODE>SIGINT</CODE> might also return normally after setting aflag that tells the program to exit at a convenient time.<P>It is not safe to return normally from the handler for a program errorsignal, because the behavior of the program when the handler functionreturns is not defined after a program error. See section <A HREF="library_21.html#SEC336" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC336">Program Error Signals</A>.<P>Handlers that return normally must modify some global variable in orderto have any effect. Typically, the variable is one that is examinedperiodically by the program during normal operation. Its data typeshould be <CODE>sig_atomic_t</CODE> for reasons described in section <A HREF="library_21.html#SEC358" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358">Atomic Data Access and Signal Handling</A>.<P>Here is a simple example of such a program. It executes the body ofthe loop until it has noticed that a <CODE>SIGALRM</CODE> signal has arrived.This technique is useful because it allows the iteration in progresswhen the signal arrives to complete before the loop exits.<P><PRE>#include <signal.h>#include <stdio.h>#include <stdlib.h>/* This flag controls termination of the main loop. */volatile sig_atomic_t keep_going = 1;/* The signal handler just clears the flag and re-enables itself. */void catch_alarm (int sig){ keep_going = 0; signal (sig, catch_alarm);}void do_stuff (void){ puts ("Doing stuff while waiting for alarm....");}intmain (void){ /* Establish a handler for SIGALRM signals. */ signal (SIGALRM, catch_alarm); /* Set an alarm to go off in a little while. */ alarm (2); /* Check the flag once in a while to see when to quit. */ while (keep_going) do_stuff (); return EXIT_SUCCESS;}</PRE><P><H3><A NAME="SEC353" HREF="library_toc.html#SEC353" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC353">Handlers That Terminate the Process</A></H3><P>Handler functions that terminate the program are typically used to causeorderly cleanup or recovery from program error signals and interactiveinterrupts.<P>The cleanest way for a handler to terminate the process is to raise thesame signal that ran the handler in the first place. Here is how to dothis:<P><PRE>volatile sig_atomic_t fatal_error_in_progress = 0;voidfatal_error_signal (int sig){ /* Since this handler is established for more than one kind of signal, it might still get invoked recursively by delivery of some other kind of signal. Use a static variable to keep track of that. */ if (fatal_error_in_progress) raise (sig); fatal_error_in_progress = 1; /* Now do the clean up actions: - reset terminal modes - kill child processes - remove lock files */ ... /* Now reraise the signal. Since the signal is blocked, it will receive its default handling, which is to terminate the process. We could just call <CODE>exit</CODE> or <CODE>abort</CODE>, but reraising the signal sets the return status from the process correctly. */ raise (sig);}</PRE><P><A NAME="IDX1560"></A><H3><A NAME="SEC354" HREF="library_toc.html#SEC354" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC354">Nonlocal Control Transfer in Handlers</A></H3><P>You can do a nonlocal transfer of control out of a signal handler usingthe <CODE>setjmp</CODE> and <CODE>longjmp</CODE> facilities (see section <A HREF="library_20.html#SEC326" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_20.html#SEC326">Non-Local Exits</A>).<P>When the handler does a nonlocal control transfer, the part of theprogram that was running will not continue. If this part of the programwas in the middle of updating an important data structure, the datastructure will remain inconsistent. Since the program does notterminate, the inconsistency is likely to be noticed later on.<P>There are two ways to avoid this problem. One is to block the signalfor the parts of the program that update important data structures.Blocking the signal delays its delivery until it is unblocked, once thecritical updating is finished. See section <A HREF="library_21.html#SEC368" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC368">Blocking Signals</A>.<P>The other way to re-initialize the crucial data structures in the signalhandler, or make their values consistent.<P>Here is a rather schematic example showing the reinitialization of oneglobal variable.<P><PRE>#include <signal.h>#include <setjmp.h>jmp_buf return_to_top_level;volatile sig_atomic_t waiting_for_input;voidhandle_sigint (int signum){ /* We may have been waiting for input when the signal arrived, but we are no longer waiting once we transfer control. */ waiting_for_input = 0; longjmp (return_to_top_level, 1);}intmain (void){ ... signal (SIGINT, sigint_handler); ... while (1) { prepare_for_command (); if (setjmp (return_to_top_level) == 0) read_and_execute_command (); }}/* Imagine this is a subroutine used by various commands. */char *read_data (){ if (input_from_terminal) { waiting_for_input = 1; ... waiting_for_input = 0; } else { ... }}</PRE><P><A NAME="IDX1561"></A><H3><A NAME="SEC355" HREF="library_toc.html#SEC355" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC355">Signals Arriving While a Handler Runs</A></H3><P>What happens if another signal arrives when your signal handler functionis running?<P>When the handler for a particular signal is invoked, that signal isnormally blocked until the handler returns. That means that if twosignals of the same kind arrive close together, the second one will beheld until the first has been handled. (The handler can explicitlyunblock the signal using <CODE>sigprocmask</CODE>, if you wan
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -