scs@adam.mit.edu (Steve Summit) (08/04/90)
Under some versions of the Bourne shell, the traditional logout script, requested with trap '. $HOME/.eliforp; exit' 0 instead causes the shell to generate a longjmp botch, and leave an annoying core file in whatever had been the current directory, upon logout. The logout script .eliforp does not execute. I have seen this bug come and go on various systems I've used; strings on the one I'm using now reveals that main.c is version 4.3 from 3/19/85 and word.c is version 4.6 from 10/31/85. (The rest of the SCCS ID's are older, most from 1983.) The bug is reminiscent of one I once tracked down in adb on a Sequent Balance 8000. The BSD-derived adb used an undocumented and hitherto-unknown-to-me setjmp/longjmp variant (names long since forgotten) which did the usual establish-context-at-top- level upon startup and revert-to-it after an error. (Why these routines existed at all, when they appeared to be a special case of setjmp/longjmp, is beyond me.) The problem was that someone at Sequent had almost-cleverly implemented this pair in terms of setjmp and longjmp; I unwittingly pulled these "Berkeley compatibility" routines out of Sequent's libc.a when compiling adb. Attractive though it may have seemed, setjmp is not a building block out of which you can build something like setjmp. A context-saving routine which calls setjmp to save the context and then returns has just invalidated that context. I mention this because something like it may be going on inside sh. I would track this down myself except that I do not have source access at the moment. Has anyone else seen it or tracked it down? (There must be one or two sh users left in the country.) Is it fixed in the current BSD release, indicating that I've simply been saddled with an obsolete copy? Steve Summit scs@adam.mit.edu
chris@mimsy.umd.edu (Chris Torek) (08/06/90)
In article <1990Aug3.230130.7347@athena.mit.edu> scs@adam.mit.edu (Steve Summit) writes: >The bug is reminiscent of one I once tracked down in adb on a >Sequent Balance 8000. The BSD-derived adb used an undocumented >and hitherto-unknown-to-me setjmp/longjmp variant (names long >since forgotten) `setexit' and `reset'. >(Why these routines existed at all, when they appeared to be a >special case of setjmp/longjmp, is beyond me.) Age. setjmp and longjmp were generalizations of setexit and reset (setexit and reset do not take a `jmp_buf', so there can only be one reset-point). >The problem was that someone at Sequent had almost-cleverly implemented >this pair in terms of setjmp and longjmp; This is a remarkably popular mistake. Setexit and reset cannot be done as routines, because reset will then attempt to jump to a stack frame that no longer exists: frame what: depth: ----- ----- 2 foo calls setexit 3 setexit calls setjmp(static_jmpbuf) 4 setjmp saves frame 3 3 setexit returns to foo 2 foo runs for a while 2 something calls reset 3 reset calls longjmp(static_jmpbuf) 4 jump is not upward (3 is not greater than 3) hence is invalid 4 longjmp calls longjmperr 5 longjmperr aborts >Attractive though it may have seemed, setjmp is not a >building block out of which you can build something like setjmp. >A context-saving routine which calls setjmp to save the context >and then returns has just invalidated that context. (right) >I mention this because something like it may be going on inside sh. No, this is a different problem. sh's `.' command is failing (`no such file or directory') and sh is doing a longjmp to a removed frame. main() calls done() which calls execexp() which calls execute() which calls failed() which calls exitsh() which decides the shell is (still) interactive and calls longjmp to return to a routine which has already returned to main(). The simplest fix is probably to add flag &= ~ttyflg; to done() before it calls execute(). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris (New campus phone system, active sometime soon: +1 301 405 2750)