sigint.htm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. <HTML>
  2. <HEAD>
  3. <link rel="SHORTCUT ICON" href="http://www.cons.org/favicon.ico">
  4. <TITLE>Proper handling of SIGINT/SIGQUIT [http://www.cons.org/cracauer/sigint.html]</TITLE>
  5. <!-- Created by: GNU m4 using $Revision: 1.20 $ of crawww.m4lib on 11-Feb-2005 -->
  6. <BODY BGCOLOR="#fff8e1">
  7. <CENTER><H2>Proper handling of SIGINT/SIGQUIT</H2></CENTER>
  8. <img src=linie.png width="100%" alt=" ">
  9. <P>
  10. <table border=1 cellpadding=4>
  11. <tr><th valign=top align=left>Abstract: </th>
  12. <td valign=top align=left>
  13. In UNIX terminal sessions, you usually have a key like
  14. <code>C-c</code> (Control-C) to immediately end whatever program you
  15. have running in the foreground. This should work even when the program
  16. you called has called other programs in turn. Everything should be
  17. aborted, giving you your command prompt back, no matter how deep the
  18. call stack is.
  19. <p>Basically, it's trivial. But the existence of interactive
  20. applications that use SIGINT and/or SIGQUIT for other purposes than a
  21. complete immediate abort make matters complicated, and - as was to
  22. expect - left us with several ways to solve the problems. Of course,
  23. existing shells and applications follow different ways.
  24. <P>This Web pages outlines different ways to solve the problem and
  25. argues that only one of them can do everything right, although it
  26. means that we have to fix some existing software.
  27. </td></tr><tr><th valign=top align=left>Intended audience: </th>
  28. <td valign=top align=left>Programmers who implement programs that catch SIGINT/SIGQUIT.
  29. <BR>Programmers who implements shells or shell-like programs that
  30. execute batches of programs.
  31. <p>Users who have problems problems getting rid of runaway shell
  32. scripts using <code>Control-C</code>. Or have interactive applications
  33. that don't behave right when sending SIGINT. Examples are emacs'es
  34. that die on Control-g or shellscript statements that sometimes are
  35. executed and sometimes not, apparently not determined by the user's
  36. intention.
  37. </td></tr><tr><th valign=top align=left>Required knowledge: </th>
  38. <td valign=top align=left>You have to know what it means to catch SIGINT or SIGQUIT and how
  39. processes are waiting for other processes (children) they spawned.
  40. </td></tr></table>
  41. <img src=linie.png width="100%" alt=" ">
  42. <H3>Basic concepts</H3>
  43. What technically happens when you press Control-C is that all programs
  44. running in the foreground in your current terminal (or virtual
  45. terminal) get the signal SIGINT sent.
  46. <p>You may change the key that triggers the signal using
  47. <code>stty</code> and running programs may remap the SIGINT-sending
  48. key at any time they like, without your intervention and without
  49. asking you first.
  50. <p>The usual reaction of a running program to SIGINT is to exit.
  51. However, not all program do an exit on SIGINT, programs are free to
  52. use the signal for other actions or to ignore it at all.
  53. <p>All programs running in the foreground receive the signal. This may
  54. be a nested "stack" of programs: You started a program that started
  55. another and the outer is waiting for the inner to exit. This nesting
  56. may be arbitrarily deep.
  57. <p>The innermost program is the one that decides what to do on SIGINT.
  58. It may exit, do something else or do nothing. Still, when the user hit
  59. SIGINT, all the outer programs are awaken, get the signal and may
  60. react on it.
  61. <H3>What we try to achieve</H3>
  62. The problem is with shell scripts (or similar programs that call
  63. several subprograms one after another).
  64. <p>Let us consider the most basic script:
  65. <PRE>
  66. #! /bin/sh
  67. program1
  68. program2
  69. </PRE>
  70. and the usual run looks like this:
  71. <PRE>
  72. $ sh myscript
  73. [output of program1]
  74. [output of program2]
  75. $
  76. </PRE>
  77. <p>Let us assume that both programs do nothing special on SIGINT, they
  78. just exit.
  79. <p>Now imagine the user hits C-c while a shellscript is executing its
  80. first program. The following programs receive SIGINT: program1 and
  81. also the shell executing the script. program1 exits.
  82. <p>But what should the shell do? If we say that it is only the
  83. innermost's programs business to react on SIGINT, the shell will do
  84. nothing special (not exit) and it will continue the execution of the
  85. script and run program2. But this is wrong: The user's intention in
  86. hitting C-c is to abort the whole script, to get his prompt back. If
  87. he hits C-c while the first program is running, he does not want
  88. program2 to be even started.
  89. <p>here is what would happen if the shell doesn't do anything:
  90. <PRE>
  91. $ sh myscript
  92. [first half of program1's output]
  93. C-c [users presses C-c]
  94. [second half of program1's output will not be displayed]
  95. [output of program2 will appear]
  96. </PRE>
  97. <p>Consider a more annoying example:
  98. <pre>
  99. #! /bin/sh
  100. # let's assume there are 300 *.dat files
  101. for file in *.dat ; do
  102. dat2ascii $dat
  103. done
  104. </pre>
  105. If your shell wouldn't end if the user hits <code>C-c</code>,
  106. <code>C-c</code> would just end <strong>one</strong> dat2ascii run and
  107. the script would continue. Thus, you had to hit <code>C-c</code> up to
  108. 300 times to end this script.
  109. <H3>Alternatives to do so</H3>
  110. <p>There are several ways to handle abortion of shell scripts when
  111. SIGINT is received while a foreground child runs:
  112. <menu>
  113. <li>As just outlined, the shellscript may just continue, ignoring the
  114. fact that the user hit <code>C-c</code>. That way, your shellscript -
  115. including any loops - would continue and you had no chance of aborting
  116. it except using the kill command after finding out the outermost
  117. shell's PID. This "solution" will not be discussed further, as it is
  118. obviously not desirable.
  119. <p><li>The shell itself exits immediately when it receives SIGINT. Not
  120. only the program called will exit, but the calling (the
  121. script-executing) shell. The first variant is to exit the shell (and
  122. therefore discontinuing execution of the script) immediately, while
  123. the background program may still be executing (remember that although
  124. the shell is just waiting for the called program to exit, it is woken
  125. up and may act). I will call the way of doing things the "IUE" (for
  126. "immediate unconditional exit") for the rest of this document.
  127. <p><li>As a variant of the former, when the shell receives SIGINT
  128. while it is waiting for a child to exit, the shell does not exit
  129. immediately. but it remembers the fact that a SIGINT happened. After
  130. the called program exits and the shell's wait ends, the shell will
  131. exit itself and hence discontinue the script. I will call the way of
  132. doing things the "WUE" (for "wait and unconditional exit") for the
  133. rest of this document.
  134. <p><li>There is also a way that the calling shell can tell whether the
  135. called program exited on SIGINT and if it ignored SIGINT (or used it
  136. for other purposes). As in the <sl>WUE</sl> way, the shell waits for
  137. the child to complete. It figures whether the program was ended on
  138. SIGINT and if so, it discontinue the script. If the program did any
  139. other exit, the script will be continued. I will call the way of doing
  140. things the "WCE" (for "wait and cooperative exit") for the rest of
  141. this document.
  142. </menu>
  143. <H3>The problem</H3>
  144. On first sight, all three solutions (IUE, WUE and WCE) all seem to do
  145. what we want: If C-c is hit while the first program of the shell
  146. script runs, the script is discontinued. The user gets his prompt back
  147. immediately. So what are the difference between these way of handling
  148. SIGINT?
  149. <p>There are programs that use the signal SIGINT for other purposes
  150. than exiting. They use it as a normal keystroke. The user is expected
  151. to use the key that sends SIGINT during a perfectly normal program
  152. run. As a result, the user sends SIGINT in situations where he/she
  153. does not want the program or the script to end.
  154. <p>The primary example is the emacs editor: C-g does what ESC does in
  155. other applications: It cancels a partially executed or prepared
  156. operation. Technically, emacs remaps the key that sends SIGINT from
  157. C-c to C-g and catches SIGINT.
  158. <p>Remember that the SIGINT is sent to all programs running in the
  159. foreground. If emacs is executing from a shell script, both emacs and
  160. the shell get SIGINT. emacs is the program that decides what to do:
  161. Exit on SIGINT or not. emacs decides not to exit. The problem arises
  162. when the shell draws its own conclusions from receiving SIGINT without
  163. consulting emacs for its opinion.
  164. <p>Consider this script:
  165. <PRE>
  166. #! /bin/sh
  167. emacs /tmp/foo
  168. cp /tmp/foo /home/user/mail/sent
  169. </PRE>
  170. <p>If C-g is used in emacs, both the shell and emacs will received
  171. SIGINT. Emacs will not exit, the user used C-g as a normal editing
  172. keystroke, he/she does not want the script to be aborted on C-g.
  173. <p>The central problem is that the second command (cp) may
  174. unintentionally be killed when the shell draws its own conclusion
  175. about the user's intention. The innermost program is the only one to
  176. judge.
  177. <H3>One more example</H3>
  178. <p>Imagine a mail session using a curses mailer in a tty. You called
  179. your mailer and started to compose a message. Your mailer calls emacs.
  180. <code>C-g</code> is a normal editing key in emacs. Technically it
  181. sends SIGINT (it was <code>C-c</code>, but emacs remapped the key) to
  182. <menu>
  183. <li>emacs
  184. <li>the shell between your mailer and emacs, the one from your mailers
  185. system("emacs /tmp/bla.44") command
  186. <li>the mailer itself
  187. <li>possibly another shell if your mailer was called by a shell script
  188. or from another application using system(3)
  189. <li>your interactive shell (which ignores it since it is interactive
  190. and hence is not relevant to this discussion)
  191. </menu>
  192. <p>If everyone just exits on SIGINT, you will be left with nothing but
  193. your login shell, without asking.
  194. <p>But for sure you don't want to be dropped out of your editor and
  195. out of your mailer back to the commandline, having your edited data
  196. and mailer status deleted.
  197. <p>Understand the difference: While <code>C-g</code> is used an a kind
  198. of abort key in emacs, it isn't the major "abort everything" key. When
  199. you use <code>C-g</code> in emacs, you want to end some internal emacs
  200. command. You don't want your whole emacs and mailer session to end.
  201. <p>So, if the shell exits immediately if the user sends SIGINT (the
  202. second of the four ways shown above), the parent of emacs would die,
  203. leaving emacs without the controlling tty. The user will lose it's
  204. editing session immediately and unrecoverable. If the "main" shell of
  205. the operating system defaults to this behavior, every editor session
  206. that is spawned from a mailer or such will break (because it is
  207. usually executed by system(3), which calls /bin/sh). This was the case
  208. in FreeBSD before I and Bruce Evans changed it in 1998.
  209. <p>If the shell recognized that SIGINT was sent and exits after the
  210. current foreground process exited (the third way of the four), the
  211. editor session will not be disturbed, but things will still not work
  212. right.
  213. <H3>A further look at the alternatives</H3>
  214. <p>Still considering this script to examine the shell's actions in the
  215. IUE, WUE and ICE way of handling SIGINT:
  216. <PRE>
  217. #! /bin/sh
  218. emacs /tmp/foo
  219. cp /tmp/foo /home/user/mail/sent
  220. </PRE>
  221. <p>The IUE ("immediate unconditional exit") way does not work at all:
  222. emacs wants to survive the SIGINT (it's a normal editing key for
  223. emacs), but its parent shell unconditionally thinks "We received
  224. SIGINT. Abort everything. Now.". The shell will exit even before emacs
  225. exits. But this will leave emacs in an unusable state, since the death
  226. of its calling shell will leave it without required resources (file
  227. descriptors). This way does not work at all for shellscripts that call
  228. programs that use SIGINT for other purposes than immediate exit. Even
  229. for programs that exit on SIGINT, but want to do some cleanup between
  230. the signal and the exit, may fail before they complete their cleanup.
  231. <p>It should be noted that this way has one advantage: If a child
  232. blocks SIGINT and does not exit at all, this way will get control back
  233. to the user's terminal. Since such programs should be banned from your
  234. system anyway, I don't think that weighs against the disadvantages.
  235. <p>WUE ("wait and unconditional exit") is a little more clever: If C-g
  236. was used in emacs, the shell will get SIGINT. It will not immediately
  237. exit, but remember the fact that a SIGINT happened. When emacs ends
  238. (maybe a long time after the SIGINT), it will say "Ok, a SIGINT
  239. happened sometime while the child was executing, the user wants the
  240. script to be discontinued". It will then exit. The cp will not be
  241. executed. But that's bad. The "cp" will be executed when the emacs
  242. session ended without the C-g key ever used, but it will not be
  243. executed when the user used C-g at least one time. That is clearly not
  244. desired. Since C-g is a normal editing key in emacs, the user expects
  245. the rest of the script to behave identically no matter what keys he
  246. used.
  247. <p>As a result, the "WUE" way is better than the "IUE" way in that it
  248. does not break SIGINT-using programs completely. The emacs session
  249. will end undisturbed. But it still does not support scripts where
  250. other actions should be performed after a program that use SIGINT for
  251. non-exit purposes. Since the behavior is basically undeterminable for
  252. the user, this can lead to nasty surprises.
  253. <p>The "WCE" way fixes this by "asking" the called program whether it
  254. exited on SIGINT or not. While emacs receives SIGINT, it does not exit
  255. on it and a calling shell waiting for its exit will not be told that
  256. it exited on SIGINT. (Although it receives SIGINT at some point in
  257. time, the system does not enforce that emacs will exit with
  258. "I-exited-on-SIGINT" status. This is under emacs' control, see below).
  259. <p>this still work for the normal script without SIGINT-using
  260. programs:</p>
  261. <PRE>
  262. #! /bin/sh
  263. program1
  264. program2
  265. </PRE>
  266. Unless program1 and program2 mess around with signal handling, the
  267. system will tell the calling shell whether the programs exited
  268. normally or as a result of SIGINT.
  269. <p>The "WCE" way then has an easy way to things right: When one called
  270. program exited with "I-exited-on-SIGINT" status, it will discontinue
  271. the script after this program. If the program ends without this
  272. status, the next command in the script is started.
  273. <p>It is important to understand that a shell in "WCE" modus does not
  274. need to listen to the SIGINT signal at all. Both in the
  275. "emacs-then-cp" script and in the "several-normal-programs" script, it
  276. will be woken up and receive SIGINT when the user hits the
  277. corresponding key. But the shell does not need to react on this event
  278. and it doesn't need to remember the event of any SIGINT, either.
  279. Telling whether the user wants to end a script is done by asking that
  280. program that has to decide, that program that interprets keystrokes
  281. from the user, the innermost program.
  282. <H3>So everything is well with WCE?</H3>
  283. Well, almost.
  284. <p>The problem with the "WCE" modus is that there are broken programs
  285. that do not properly communicate the required information up to the
  286. calling program.
  287. <p>Unless a program messes with signal handling, the system does this
  288. automatically.
  289. <p>There are programs that want to exit on SIGINT, but they don't let
  290. the system do the automatic exit, because they want to do some
  291. cleanup. To do so, they catch SIGINT, do the cleanup and then exit by
  292. themselves.
  293. <p>And here is where the problem arises: Once they catch the signal,
  294. the system will no longer communicate the "I-exited-on-SIGINT" status
  295. to the calling program automatically. Even if the program exit
  296. immediately in the signal handler of SIGINT. Once it catches the
  297. signal, it has to take care of communicating the signal status
  298. itself.
  299. <p>Some programs don't do this. On SIGINT, they do cleanup and exit
  300. immediately, but the calling shell isn't told about the non-normal exit
  301. and it will call the next program in the script.
  302. <p>As a result, the user hits SIGINT and while one program exits, the
  303. shellscript continues. To him/her it looks like the shell fails to
  304. obey to his abortion command.
  305. <p>Both IUE or WUE shell would not have this problem, since they
  306. discontinue the script on their own. But as I said, they don't support
  307. programs using SIGINT for non-exiting purposes, no matter whether
  308. these programs properly communicate their signal status to the calling
  309. shell or not.
  310. <p>Since some shell in wide use implement the WUE way (and some even
  311. IUE), there is a considerable number of broken programs out there that
  312. break WCE shells. The programmers just don't recognize it if their
  313. shell isn't WCE.
  314. <H3>How to be a proper program</H3>
  315. <p>(Short note in advance: What you need to achieve is that
  316. WIFSIGNALED(status) is true in the calling program and that
  317. WTERMSIG(status) returns SIGINT.)
  318. <p>If you don't catch SIGINT, the system automatically does the right
  319. thing for you: Your program exits and the calling program gets the
  320. right "I-exited-on-SIGINT" status after waiting for your exit.
  321. <p>But once you catch SIGINT, you have to act.
  322. <p>Decide whether the SIGINT is used for exit/abort purposes and hence
  323. a shellscript calling this program should discontinue. This is
  324. hopefully obvious. If you just need to do some cleanup on SIGINT, but
  325. then exit immediately, the answer is "yes".
  326. <p>If so, you have to tell the calling program about it by exiting
  327. with the "I-exited-on-SIGINT" status.
  328. <p>There is no other way of doing this than to kill yourself with a
  329. SIGINT signal. Do it by resetting the SIGINT handler to SIG_DFL, then
  330. send yourself the signal.
  331. <PRE>
  332. void sigint_handler(int sig)
  333. {
  334. <do some cleanup>
  335. signal(SIGINT, SIG_DFL);
  336. kill(getpid(), SIGINT);
  337. }
  338. </PRE>
  339. Notes:
  340. <MENU>
  341. <LI>You cannot "fake" the proper exit status by an exit(3) with a
  342. special numeric value. People often assume this since the manuals for
  343. shells often list some return value for exactly this. But this is just
  344. a convention for your shell script. It does not work from one UNIX API
  345. program to another.
  346. <P>All that happens is that the shell sets the "$?" variable to a
  347. special numeric value for the convenience of your script, because your
  348. script does not have access to the lower-lever UNIX status evaluation
  349. functions. This is just an agreement between your script and the
  350. executing shell, it does not have any meaning in other contexts.
  351. <P><LI>Do not use kill(0, SIGINT) without consulting the manul for
  352. your OS implementation. I.e. on BSD, this would not send the signal to
  353. the current process, but to all processes in the group.
  354. <P><LI>POSIX 1003.1 allows all these calls to appear in signal
  355. handlers, so it is portable.
  356. </MENU>
  357. <p>In a bourne shell script, you can catch signals using the
  358. <code>trap</code> command. Here, the same as for C programs apply. If
  359. the intention of SIGINT is to end your program, you have to exit in a
  360. way that the calling programs "sees" that you have been killed. If
  361. you don't catch SIGINT, this happened automatically, but of you catch
  362. SIGINT, i.e. to do cleanup work, you have to end the program by
  363. killing yourself, not by calling exit.
  364. <p>Consider this example from FreeBSD's <code>mkdep</code>, which is a
  365. bourne shell script.
  366. <pre>
  367. TMP=_mkdep$$
  368. trap 'rm -f $TMP ; trap 2 ; kill -2 $$' 1 2 3 13 15
  369. </pre>
  370. Yes, you have to do it the hard way. It's even more annoying in shell
  371. scripts than in C programs since you can't "pre-delete" temporary
  372. files (which isn't really portable in C, though).
  373. <P>All this applies to programs in all languages, not only C and
  374. bourne shell. Every language implementation that lets you catch SIGINT
  375. should also give you the option to reset the signal and kill yourself.
  376. <P>It is always desirable to exit the right way, even if you don't
  377. expect your usual callers to depend on it, some unusual one will come
  378. along. This proper exit status will be needed for WCE and will not
  379. hurt when the calling shell uses IUE or WUE.
  380. <H3>How to be a proper shell</H3>
  381. All this applies only for the script-executing case. Most shells will
  382. also have interactive modes where things are different.
  383. <MENU>
  384. <LI>Do nothing special when SIGINT appears while you wait for a child.
  385. You don't even have to remember that one happened.
  386. <P><LI>Wait for child to exit, get the exit status. Do not truncate it
  387. to type char.
  388. <P><LI>Look at WIFSIGNALED(status) and WTERMSIG(status) to tell
  389. whether the child says "I exited on SIGINT: in my opinion the user
  390. wants the shellscript to be discontinued".
  391. <P><LI>If the latter applies, discontinue the script.
  392. <P><LI>Exit. But since a shellscript may in turn be called by a
  393. shellscript, you need to make sure that you properly communicate the
  394. discontinue intention to the calling program. As in any other program
  395. (see above), do
  396. <PRE>
  397. signal(SIGINT, SIG_DFL);
  398. kill(getpid(), SIGINT);
  399. </PRE>
  400. </MENU>
  401. <H3>Other remarks</H3>
  402. Although this web page talks about SIGINT only, almost the same issues
  403. apply to SIGQUIT, including proper exiting by killing yourself after
  404. catching the signal and proper reaction on the WIFSIGNALED(status)
  405. value. One notable difference for SIGQUIT is that you have to make
  406. sure that not the whole call tree dumps core.
  407. <H3>What to fight</H3>
  408. Make sure all programs <em>really</em> kill themselves if they react
  409. to SIGINT or SIGQUIT and intend to abort their operation as a result
  410. of this signal. Programs that don't use SIGINT/SIGQUIT as a
  411. termination trigger - but as part of normal operation - don't kill
  412. themselves, but do a normal exit instead.
  413. <p>Make sure people understand why you can't fake an exit-on-signal by
  414. doing exit(...) using any numerical status.
  415. <p>Make sure you use a shell that behaves right. Especially if you
  416. develop programs, since it will help seeing problems.
  417. <H3>Concrete examples how to fix programs:</H3>
  418. <ul>
  419. <li>The fix for FreeBSD's
  420. <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/time/time.c.diff?r1=1.10&r2=1.11">time(1)</A>. This fix is the best example, it's quite short and clear and
  421. it fixes a case where someone tried to fake signal exit status by a
  422. numerical value. And the complete program is small.
  423. <p><li>Fix for FreeBSD's
  424. <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/truss/main.c.diff?r1=1.9&r2=1.10">truss(1)</A>.
  425. <p><li>The fix for FreeBSD's
  426. <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/mkdep/mkdep.gcc.sh.diff?r1=1.8.2.1&r2=1.8.2.2">mkdep(1)</A>, a shell script.
  427. <p><li>Fix for FreeBSD's make(1), <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/make/job.c.diff?r1=1.9&r2=1.10">part 1</A>,
  428. <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/make/compat.c.diff?r1=1.10&r2=1.11">part 2</A>.
  429. </ul>
  430. <H3>Testsuite for shells</H3>
  431. I have a collection of shellscripts that test shells for the
  432. behavior. See my <A HREF="download/">download dir</A> to get the newest
  433. "sh-interrupt" files, either as a tarfile or as individual file for
  434. online browsing. This isn't really documented, besides from the
  435. comments the scripts echo.
  436. <H3>Appendix 1 - table of implementation choices</H3>
  437. <table border cellpadding=2>
  438. <tr valign=top>
  439. <th>Method sign</th>
  440. <th>Does what?</th>
  441. <th>Example shells that implement it:</th>
  442. <th>What happens when a shellscript called emacs, the user used
  443. <code>C-g</code> and the script has additional commands in it?</th>
  444. <th>What happens when a shellscript called emacs, the user did not use
  445. <code>C-c</code> and the script has additional commands in it?</th>
  446. <th>What happens if a non-interactive child catches SIGINT?</th>
  447. <th>To behave properly, children must do what?</th>
  448. </tr>
  449. <tr valign=top align=left>
  450. <td>IUE</td>
  451. <td>The shell executing a script exits immediately if it receives
  452. SIGINT.</td>
  453. <td>4.4BSD ash (ash), NetBSD, FreeBSD prior to 3.0/22.8</td>
  454. <td>The editor session is lost and subsequent commands are not
  455. executed.</td>
  456. <td>The editor continues as normal and the subsequent commands are
  457. executed. </td>
  458. <td>The scripts ends immediately, returning to the caller even before
  459. the current foreground child of the shell exits. </td>
  460. <td>It doesn't matter what the child does or how it exits, even if the
  461. child continues to operate, the shell returns. </td>
  462. </tr>
  463. <tr valign=top align=left>
  464. <td>WUE</td>
  465. <td>If the shell executing a script received SIGINT while a foreground
  466. process was running, it will exit after that child's exit.</td>
  467. <td>pdksh (OpenBSD /bin/sh)</td>
  468. <td>The editor continues as normal, but subsequent commands from the
  469. script are not executed.</td>
  470. <td>The editor continues as normal and subsequent commands are
  471. executed. </td>
  472. <td>The scripts returns to its caller after the current foreground
  473. child exits, no matter how the child exited. </td>
  474. <td>It doesn't matter how the child exits (signal status or not), but
  475. if it doesn't return at all, the shell will not return. In no case
  476. will further commands from the script be executed. </td>
  477. </tr>
  478. <tr valign=top align=left>
  479. <td>WCE</td>
  480. <td>The shell exits if a child signaled that it was killed on a
  481. signal (either it had the default handler for SIGINT or it killed
  482. itself). </td>
  483. <td>bash (Linux /bin/sh), most commercial /bin/sh, FreeBSD /bin/sh
  484. from 3.0/2.2.8.</td>
  485. <td>The editor continues as normal and subsequent commands are
  486. executed. </td>
  487. <td>The editor continues as normal and subsequent commands are
  488. executed. </td>
  489. <td>The scripts returns to its caller after the current foreground
  490. child exits, but only if the child exited with signal status. If
  491. the child did a normal exit (even if it received SIGINT, but catches
  492. it), the script will continue. </td>
  493. <td>The child must be implemented right, or the user will not be able
  494. to break shell scripts reliably.</td>
  495. </tr>
  496. </table>
  497. <P><img src=linie.png width="100%" alt=" ">
  498. <BR>&copy;2005 Martin Cracauer &lt;cracauer @ cons.org&gt;
  499. <A HREF="http://www.cons.org/cracauer/">http://www.cons.org/cracauer/</A>
  500. <BR>Last changed: $Date: 2005/02/11 21:44:43 $
  501. </BODY></HTML>