1 .\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
3 .\" Redistribution and use in source and binary forms, with or without
4 .\" modification, are permitted provided that the following conditions are
7 .\" Redistributions of source code and documentation must retain the above
8 .\" copyright notice, this list of conditions and the following
11 .\" Redistributions in binary form must reproduce the above copyright
12 .\" notice, this list of conditions and the following disclaimer in the
13 .\" documentation and/or other materials provided with the distribution.
15 .\" All advertising materials mentioning features or use of this software
16 .\" must display the following acknowledgement:
18 .\" This product includes software developed or owned by Caldera
19 .\" International, Inc. Neither the name of Caldera International, Inc.
20 .\" nor the names of other contributors may be used to endorse or promote
21 .\" products derived from this software without specific prior written
24 .\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
25 .\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
26 .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 .\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
29 .\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 .\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 .\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
34 .\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
35 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 .\" @(#)p6 8.1 (Berkeley) 6/8/93
42 SIGNALS \(em INTERRUPTS AND ALL THAT
44 This section is concerned with how to
45 deal gracefully with signals from
46 the outside world (like interrupts), and with program faults.
47 Since there's nothing very useful that
48 can be done from within C about program
49 faults, which arise mainly from illegal memory references
50 or from execution of peculiar instructions,
51 we'll discuss only the outside-world signals:
53 which is sent when the
61 caused by hanging up the phone;
67 When one of these events occurs,
70 processes which were started
71 from the corresponding terminal;
72 unless other arrangements have been made,
74 terminates the process.
77 case, a core image file is written for debugging
80 The routine which alters the default action
84 It has two arguments: the first specifies the signal, and the second
85 specifies how to treat it.
86 The first argument is just a number code, but the second is the
87 address is either a function, or a somewhat strange code
88 that requests that the signal either be ignored, or that it be
89 given the default action.
92 gives names for the various arguments, and should always be included
93 when signals are used.
98 signal(SIGINT, SIG_IGN);
100 causes interrupts to be ignored, while
102 signal(SIGINT, SIG_DFL);
104 restores the default action of process termination.
107 returns the previous value of the signal.
108 The second argument to
110 may instead be the name of a function
111 (which has to be declared explicitly if
112 the compiler hasn't seen it already).
113 In this case, the named routine will be called
114 when the signal occurs.
115 Most commonly this facility is used
116 to allow the program to clean up
117 unfinished business before terminating, for example to
118 delete a temporary file:
126 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
127 signal(SIGINT, onintr);
141 Why the test and the double call to
143 Recall that signals like interrupt are sent to
146 processes started from a particular terminal.
147 Accordingly, when a program is to be run
151 the shell turns off interrupts for it
152 so it won't be stopped by interrupts intended for foreground processes.
153 If this program began by announcing that all interrupts were to be sent
157 that would undo the shell's effort to protect it
158 when run in the background.
160 The solution, shown above, is to test the state of interrupt handling,
161 and to continue to ignore interrupts if they are already being ignored.
163 depends on the fact that
165 returns the previous state of a particular signal.
166 If signals were already being ignored, the process should continue to ignore them;
167 otherwise, they should be caught.
169 A more sophisticated program may wish to intercept
170 an interrupt and interpret it as a request
171 to stop what it is doing
172 and return to its own command-processing loop.
173 Think of a text editor:
174 interrupting a long printout should not cause it
175 to terminate and lose the work
177 The outline of the code for this case is probably best written like this:
185 int (*istat)(), onintr();
187 istat = signal(SIGINT, SIG_IGN); /* save original status */
188 setjmp(sjbuf); /* save current stack position */
189 if (istat != SIG_IGN)
190 signal(SIGINT, onintr);
192 /* main processing loop */
198 printf("\enInterrupt\en");
199 longjmp(sjbuf); /* return to saved state */
206 an object in which the state
209 is such an object; it is an array of some sort.
214 When an interrupt occurs,
215 a call is forced to the
218 which can print a message, set flags, or whatever.
220 takes as argument an object stored into by
223 to the location after the call to
225 so control (and the stack level) will pop back
226 to the place in the main routine where
227 the signal is set up and the main loop entered.
228 Notice, by the way, that
230 gets set again after an interrupt occurs.
231 This is necessary; most signals are automatically
232 reset to their default action when they occur.
234 Some programs that want to detect signals simply can't be stopped
235 at an arbitrary point,
236 for example in the middle of updating a linked list.
237 If the routine called on occurrence of a signal
239 returns instead of calling
243 execution will continue
244 at the exact point it was interrupted.
245 The interrupt flag can then be tested later.
247 There is one difficulty associated with this
249 Suppose the program is reading the
250 terminal when the interrupt is sent.
251 The specified routine is duly called; it sets its flag
253 If it were really true, as we said
254 above, that ``execution resumes at the exact point it was interrupted,''
255 the program would continue reading the terminal
256 until the user typed another line.
257 This behavior might well be confusing, since the user
258 might not know that the program is reading;
259 he presumably would prefer to have the signal take effect instantly.
260 The method chosen to resolve this difficulty
261 is to terminate the terminal read when execution
262 resumes after the signal, returning an error code
263 which indicates what happened.
265 Thus programs which catch and resume
266 execution after signals should be prepared for ``errors''
267 which are caused by interrupted
269 (The ones to watch out for are reads from a terminal,
278 resets the interrupt signal, and returns,
279 should usually include code like the following when it reads
282 if (getchar() == EOF)
284 /* EOF caused by interrupt */
286 /* true end-of-file */
289 A final subtlety to keep in mind becomes important
290 when signal-catching is combined with execution of other programs.
291 Suppose a program catches interrupts, and also includes
292 a method (like ``!'' in the editor)
293 whereby other programs can be executed.
294 Then the code should look something like this:
298 signal(SIGINT, SIG_IGN); /* ignore interrupts */
299 wait(&status); /* until the child is done */
300 signal(SIGINT, onintr); /* restore interrupts */
303 Again, it's not obvious but not really difficult.
304 Suppose the program you call catches its own interrupts.
305 If you interrupt the subprogram,
306 it will get the signal and return to its
307 main loop, and probably read your terminal.
308 But the calling program will also pop out of
309 its wait for the subprogram and read your terminal.
310 Having two processes reading
311 your terminal is very unfortunate,
312 since the system figuratively flips a coin to decide
313 who should get each line of input.
314 A simple way out is to have the parent program
315 ignore interrupts until the child is done.
316 This reasoning is reflected in the standard I/O library function
321 system(s) /* run command string s */
325 register int (*istat)(), (*qstat)();
327 if ((pid = fork()) == 0) {
328 execl("/bin/sh", "sh", "-c", s, 0);
331 istat = signal(SIGINT, SIG_IGN);
332 qstat = signal(SIGQUIT, SIG_IGN);
333 while ((w = wait(&status)) != pid && w != -1)
337 signal(SIGINT, istat);
338 signal(SIGQUIT, qstat);
343 As an aside on declarations,
346 obviously has a rather strange second argument.
347 It is in fact a pointer to a function delivering an integer,
348 and this is also the type of the signal routine itself.
353 have the right type, but are chosen so they coincide with
354 no possible actual functions.
355 For the enthusiast, here is how they are defined for the PDP-11;
356 the definitions should be sufficiently ugly
357 and nonportable to encourage use of the include file.
359 #define SIG_DFL (int (*)())0
360 #define SIG_IGN (int (*)())1