rosen@gypsy.UUCP (06/06/85)
/* This program was compiled under 4.2BSD on a VAX; it doesn't work the way it should (I get a 'longjmp botch' message). If I compile the same exact program on a Sun running 4.2BSD it works fine. I know that setjmp() and longjmp() work on a Vax, but why is this simple program giving me a problem? I've been told that this program is too simple for setjmp() and longjmp(). This appears to be true, because if I complicate the code just a bit, it will work. What's going on? */ /* setjmp() - longjmp() test program */ #include <setjmp.h> static jmp_buf env; int mode; main(){ foo(); longjmp(env, 1); } foo(){ mode = setjmp(env); if (mode != 0) magic(); } magic() { printf("HERE I AM\n"); exit(0); } /* End of code */ /* Steve Rosen Siemens Research and Technology Laboratories Princeton, NJ USENET: {ihnp4|princeton|adrvax}!siemens!rosen ARPA: princeton!siemens!rosen@TOPAZ */
henry@utzoo.UUCP (Henry Spencer) (06/07/85)
> This program was compiled under 4.2BSD on a VAX; it doesn't work the way it > should (I get a 'longjmp botch' message). If I compile the same exact > program on a Sun running 4.2BSD it works fine. I know that setjmp() and > longjmp() work on a Vax, but why is this simple program giving me a problem? > ... > main(){ > foo(); > longjmp(env, 1); > } > > foo(){ > mode = setjmp(env); > ... > } To quote the 4.2BSD setjmp(3) manual page (as well as all previous setjmp manual pages): [longjmp] returns in such a way that execution continues as if the call of setjmp had jsut returned ... to the function that invoked setjmp, *which must not itself have returned in the interim*. [emphasis added] In other words, your code is wrong. Put the setjmp in main(), or the longjmp in foo(), and it will be correct. It is only accidental that it works on some machines as it is. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
jim@ISM780B.UUCP (06/08/85)
"Forward, into the past!" -- Firesign Theatre If you longjmp into a routine that has already returned, just where do you expect to be? There is such a thing as stack discipline. The routine that calls setjmp must be an ancestor of (or equal to, which is broken on some implementations, such as pdp11 SysIII) the routine that calls longjmp. foo is not an ancestor of main. The VAX 4.2BSD version is correct; it backtraces the stack so the register variables are restored properly. The Sun version is, technically, incorrect; it saves the registers and sp in setjmp and simply restores them in longjmp. For details of why this is wrong, refer to the archives; this has been discussed to death. For details of why a correct implementation appears too costly (extra overhead on every call), see same. Also discussed there was the simple, clever technique used by the Amsterdam Compiler Kit, namely any routine that calls a routine called "setjmp" doesn't use register variables; this doesn't work only if you call setjmp indirectly, which is a rather bizarre and foolish thing to do. -- Jim Balter, INTERACTIVE Systems (ima!jim)
chris@umcp-cs.UUCP (Chris Torek) (06/08/85)
Your code has a nasty little no-no in it: it longjmp's after the stack environment in which the setjmp was done has been deallocated. No surprise it fails ``at random''. Watch: --------#include <setjmp.h> --------static jmp_buf env; --------int mode; --------main() { active: env=uninit, mode=0, main() -------- foo(); [expand foo()] []------foo() { active: env=uninit, mode=0, main(), foo() []------ mode = setjmp(env); active: env=foo(), mode=0, main(), foo() []------ if (mode != 0) magic(); []------} [return to main()] active: env=foo() [defunct], mode=0, main() -------- longjmp(env, 1); Oops. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
gwyn@brl-tgr.ARPA (06/08/85)
> main(){ > foo(); > longjmp(env, 1); > } > > foo(){ > > mode = setjmp(env); > if (mode != 0) magic(); > } "If longjmp is called even though env was never primed by a call to setjmp, or when the last such call was in a function which has since returned, absolute chaos is guaranteed." - System V Interface Definition You see, foo()'s stack frame has been totally trashed after he returned (e.g., arguments to longjmp were pushed onto the stack at addresses that were formerly part of foo()'s stack frame), and when the longjmp attempts to reactivate it it no longer makes any sense.. Sometimes it may work by accident, but it WILL be an accident.
stephen@dcl-cs.UUCP (06/09/85)
In article <44700008@gypsy.UUCP> rosen@gypsy.UUCP writes: >This program was compiled under 4.2BSD on a VAX; it doesn't work the way it >should (I get a 'longjmp botch' message). If I compile the same exact >program on a Sun running 4.2BSD it works fine. I know that setjmp() and >longjmp() work on a Vax, but why is this simple program giving me a problem? > >/* setjmp() - longjmp() test program */ >#include <setjmp.h> >static jmp_buf env; >int mode; > >main(){ > foo(); > longjmp(env, 1); >} > >foo(){ > > mode = setjmp(env); > if (mode != 0) magic(); >} It has always been my understanding that "longjmp()" is used to jump OUT of routines - not INTO them! -- Name: Stephen J. Muir Project:Alvey ECLIPSE Distribution JANET: stephen@uk.ac.lancs.comp DARPA: stephen%lancs.comp@ucl-cs UUCP: ...!ukc!icdoc!dcl-cs!stephen Phone: +44 524 65201 Ext. 4599 Post: Department of Computing, University of Lancaster, Bailrigg, Lancaster. LA1 4YR
faustus@ucbcad.UUCP (Wayne A. Christopher) (06/09/85)
> main(){ > foo(); > longjmp(env, 1); > } > > foo(){ > > mode = setjmp(env); > if (mode != 0) magic(); > } I think the problem is that you can only longjmp back to somewhere below where you are on the stack. It resets things like the stack and argument pointers, and if you have already returned from the routine where you did the setjmp, you will have problems... I don't know exactly how this would work, but this is certainly not an intended use of longjmp... Wayne