home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / c / 11463 < prev    next >
Encoding:
Internet Message Format  |  1992-07-22  |  5.0 KB

  1. Path: sparky!uunet!mcsun!fuug!demos!kiae!glas!demos!athena.mit!adam.mit.edu!scs
  2. From: scs@adam.mit.edu
  3. Newsgroups: comp.lang.c
  4. Date: 18 Jul 92 03:25 MDT
  5. Subject: Re: trapping "control C"
  6. Sender: Notesfile to Usenet Gateway <notes@glas.apc.org>
  7. Message-ID: <1992Jul17.232515.6365@athena.mit>
  8. References: <13t9osINNqam@darkstar.ucsc.edu>
  9. Nf-ID: #R:13t9osINNqam@darkstar.ucsc.edu:-1109617974:1992Jul17.232515.6365@athena.mit:617269070:001:4652
  10. Nf-From: adam.mit.edu!scs    Jul 18 03:25:00 1992
  11. Lines: 104
  12.  
  13.  
  14. In articles <1992Jul14.084225.20933@seas.smu.edu>,
  15. <1992Jul14.084757.21838@seas.smu.edu>, and
  16. <1992Jul14.085932.22581@seas.smu.edu>,
  17. Mustafa Kocaturk (mustafa@seas.smu.edu) writes:
  18. >  fprintf(stderr,
  19. >   "Installing signal handler. Previous value=%p\n",signal(SIGINT,hand));
  20.  
  21. Ignoring the curious printout of signal()'s return value (which
  22. is obviously for demonstration purposes only), there is a subtle
  23. bug here.
  24.  
  25. In article <1992Jul17.082746.13375@ibmpcug.co.uk>,
  26. Matthew Farwell (dylan@ibmpcug.co.uk) correctly writes:
  27. >     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  28. >         signal(SIGINT, handler);
  29.  
  30. As Kernighan and Ritchie say, in an unfortunately fairly obscure
  31. paper [1],
  32.  
  33.     Why the test and the double call to signal?  Recall that
  34.     signals like interrupt are sent to *all* processes
  35.     started from a particular terminal.  Accordingly, when a
  36.     program is to be run non-interactively (started by & ),
  37.     the shell turns off interrupts for it so it won't be
  38.     stopped by interrupts intended for foreground processes.
  39.     If this program began by announcing that all interrupts
  40.     were to be sent to the [signal handling] routine
  41.     regardless, that would undo the shell's effort to protect
  42.     it when run in the background.
  43.  
  44.     The solution, shown above, is to test the state of
  45.     interrupt handling, and to continue to ignore interrupts
  46.     if they are already being ignored.  The code as written
  47.     depends on the fact that signal returns the previous
  48.     state of a particular signal.  If signals were already
  49.     being ignored, the process should continue to ignore
  50.     them; otherwise, they should be caught.
  51.  
  52. This bug (catching SIGINT unilaterally, without first testing if
  53. it is being ignored) is rampant, because it is immaterial if you
  54. don't have multitasking and background processes, and because
  55. even on Unix it (the bug) is not noticed under the C shell.
  56. (csh, in conjunction with the "new" terminal driver, arranges
  57. that keyboard interrupt signals are sent only to the foreground
  58. process group, not to "all processes started from a particular
  59. terminal.")
  60.  
  61. Readers of this group are excused for not having known this, and
  62. for not having read the above-quoted paper, since this is not
  63. comp.unix.anything .
  64.  
  65. Finally, in article <1992Jul17.141248.4837@mdd.comm.mot.com>,
  66. Bill Mitchell (mitchell@mdd.comm.mot.com) writes:
  67. > Having been recently bitten by a signal handler, I thought I'd comment here.
  68. > [quote about synchronization and other problems which can occur
  69. > in handling signals, including the fact that a portable program
  70. > can safely take very few actions within a signal handler.]
  71. > The case above is pretty vanilla, except for the as-yet undefined cleanup,
  72. > since the program terminates from within the handler.
  73.  
  74. (Actually, "the case above" was not really vanilla, in that it
  75. included a printf in a signal handler, one of the more worrisome
  76. cases, although it was to stderr, which is less dangerous.)
  77.  
  78. Signal handling is really one of the cases where portability and
  79. pragmatism collide head-on.  As Bill noted, it is generally
  80. agreed that the only truly portable thing to do in a signal
  81. handler is to set a flag (of a special type, sig_atomic_t, at
  82. that) and return.  (Although one part of the ANSI C Standard
  83. seems to say that longjmp must work correctly from within any
  84. signal handler, other parts say that virtually no library
  85. functions are guaranteed to work if called from asynchronous
  86. signal handlers [2].)
  87.  
  88. The problem, of course, with simply setting a flag in a signal
  89. handler and returning, and then testing the flag synchronously in
  90. the mainline of the program, is that the tests may have to be
  91. repeated in any number of loops, and if (as it evolves) the
  92. program ever happens to have a loop which simultaneously (a)
  93. contains no test on the interrupt flag and (b) can be made to run
  94. infinitely, the program will be uninterruptible.  (A common
  95. strategy is to have the interrupt handler detect if the flag is
  96. already set, i.e. if control-C has been pressed two or more times
  97. in succession without the flag having been noticed by the
  98. mainline, and abort in that case.)
  99.  
  100. I don't have a pious moral to end with this time -- portable
  101. signal handling is just plain hard.  It's helpful, however, to
  102. avoid the problem if possible by not putting any control-C
  103. handling at all into programs which don't have a real need for
  104. it.
  105.  
  106.                     Steve Summit
  107.                     scs@adam.mit.edu
  108.  
  109. [1]    Brian W. Kernighan and Dennis M. Ritchie, "UNIX
  110.     Programming -- Second Edition", Bell Labs Technical
  111.     Memorandum 78-1273-9, October 2, 1978 [widely reprinted
  112.     in volume 2 of the Unix Programmer's Manual].
  113.  
  114. [2]    ANSI X3.159 [the ANSI C Standard], sections 4.6.2.1 and
  115.     4.7.1.1, respectively.
  116.  
  117.