home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!fuug!demos!kiae!glas!demos!athena.mit!adam.mit.edu!scs
- From: scs@adam.mit.edu
- Newsgroups: comp.lang.c
- Date: 18 Jul 92 03:25 MDT
- Subject: Re: trapping "control C"
- Sender: Notesfile to Usenet Gateway <notes@glas.apc.org>
- Message-ID: <1992Jul17.232515.6365@athena.mit>
- References: <13t9osINNqam@darkstar.ucsc.edu>
- Nf-ID: #R:13t9osINNqam@darkstar.ucsc.edu:-1109617974:1992Jul17.232515.6365@athena.mit:617269070:001:4652
- Nf-From: adam.mit.edu!scs Jul 18 03:25:00 1992
- Lines: 104
-
-
- In articles <1992Jul14.084225.20933@seas.smu.edu>,
- <1992Jul14.084757.21838@seas.smu.edu>, and
- <1992Jul14.085932.22581@seas.smu.edu>,
- Mustafa Kocaturk (mustafa@seas.smu.edu) writes:
- > fprintf(stderr,
- > "Installing signal handler. Previous value=%p\n",signal(SIGINT,hand));
-
- Ignoring the curious printout of signal()'s return value (which
- is obviously for demonstration purposes only), there is a subtle
- bug here.
-
- In article <1992Jul17.082746.13375@ibmpcug.co.uk>,
- Matthew Farwell (dylan@ibmpcug.co.uk) correctly writes:
- > if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- > signal(SIGINT, handler);
-
- As Kernighan and Ritchie say, in an unfortunately fairly obscure
- paper [1],
-
- Why the test and the double call to signal? Recall that
- signals like interrupt are sent to *all* processes
- started from a particular terminal. Accordingly, when a
- program is to be run non-interactively (started by & ),
- the shell turns off interrupts for it so it won't be
- stopped by interrupts intended for foreground processes.
- If this program began by announcing that all interrupts
- were to be sent to the [signal handling] routine
- regardless, that would undo the shell's effort to protect
- it when run in the background.
-
- The solution, shown above, is to test the state of
- interrupt handling, and to continue to ignore interrupts
- if they are already being ignored. The code as written
- depends on the fact that signal returns the previous
- state of a particular signal. If signals were already
- being ignored, the process should continue to ignore
- them; otherwise, they should be caught.
-
- This bug (catching SIGINT unilaterally, without first testing if
- it is being ignored) is rampant, because it is immaterial if you
- don't have multitasking and background processes, and because
- even on Unix it (the bug) is not noticed under the C shell.
- (csh, in conjunction with the "new" terminal driver, arranges
- that keyboard interrupt signals are sent only to the foreground
- process group, not to "all processes started from a particular
- terminal.")
-
- Readers of this group are excused for not having known this, and
- for not having read the above-quoted paper, since this is not
- comp.unix.anything .
-
- Finally, in article <1992Jul17.141248.4837@mdd.comm.mot.com>,
- Bill Mitchell (mitchell@mdd.comm.mot.com) writes:
- > Having been recently bitten by a signal handler, I thought I'd comment here.
- > [quote about synchronization and other problems which can occur
- > in handling signals, including the fact that a portable program
- > can safely take very few actions within a signal handler.]
- > The case above is pretty vanilla, except for the as-yet undefined cleanup,
- > since the program terminates from within the handler.
-
- (Actually, "the case above" was not really vanilla, in that it
- included a printf in a signal handler, one of the more worrisome
- cases, although it was to stderr, which is less dangerous.)
-
- Signal handling is really one of the cases where portability and
- pragmatism collide head-on. As Bill noted, it is generally
- agreed that the only truly portable thing to do in a signal
- handler is to set a flag (of a special type, sig_atomic_t, at
- that) and return. (Although one part of the ANSI C Standard
- seems to say that longjmp must work correctly from within any
- signal handler, other parts say that virtually no library
- functions are guaranteed to work if called from asynchronous
- signal handlers [2].)
-
- The problem, of course, with simply setting a flag in a signal
- handler and returning, and then testing the flag synchronously in
- the mainline of the program, is that the tests may have to be
- repeated in any number of loops, and if (as it evolves) the
- program ever happens to have a loop which simultaneously (a)
- contains no test on the interrupt flag and (b) can be made to run
- infinitely, the program will be uninterruptible. (A common
- strategy is to have the interrupt handler detect if the flag is
- already set, i.e. if control-C has been pressed two or more times
- in succession without the flag having been noticed by the
- mainline, and abort in that case.)
-
- I don't have a pious moral to end with this time -- portable
- signal handling is just plain hard. It's helpful, however, to
- avoid the problem if possible by not putting any control-C
- handling at all into programs which don't have a real need for
- it.
-
- Steve Summit
- scs@adam.mit.edu
-
- [1] Brian W. Kernighan and Dennis M. Ritchie, "UNIX
- Programming -- Second Edition", Bell Labs Technical
- Memorandum 78-1273-9, October 2, 1978 [widely reprinted
- in volume 2 of the Unix Programmer's Manual].
-
- [2] ANSI X3.159 [the ANSI C Standard], sections 4.6.2.1 and
- 4.7.1.1, respectively.
-
-