Path: utzoo!attcan!uunet!lll-winken!ncis.llnl.gov!helios.ee.lbl.gov!pasteur!ames!ncar!tank!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Behaviour of setjmp/longjmp and registers Message-ID: <15626@mimsy.UUCP> Date: 25 Jan 89 15:36:06 GMT References: <25@torsqnt.UUCP> <8867@bloom-beacon.MIT.EDU> <7283@polyslo.CalPoly.EDU> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 72 In article <7283@polyslo.CalPoly.EDU> cquenel@polyslo.CalPoly.EDU (96 more school days) writes: >-- The real purpose of setjmp/longjmp is as a global goto > when you have to go around the stack. It shouldn't > need any "features" that make it easier to use. ... >-- No semi-legitimate uses of setjmp/longjmp that come to mind > actually would require the restoral of variables to function. These are the key points (and, incidentally, tie in to the `B&D' discussion in comp.lang.misc). For the sake of argument (which is to say that I do not necessarily believe this myself), consider the following use of setjmp/longjmp: /* return type of signal functions, either int or void */ typedef void sigreturn_t; static struct jbstack { jmp_buf cur; jmp_buf *prev; } *jbstack; sigreturn_t stop(int sig) { longjmp(jbstack->cur, 1); } struct foo *timed_fiddle_with(struct foo *base) { int fd; sigreturn_t (*oldalarm)(); struct jbstack j; j.prev = jbstack; jbstack = &j; if (setjmp(&j.cur)) { /* timeout */ jbstack = j.prev; (void) signal(SIGALRM, oldalarm); free((void *)base); return NULL; } (void) alarm(base->timeout); oldalarm = signal(SIGALARM, stop); fd = open(base->name, base->mode); (void) alarm(0); base->fd = fd; jbstack = j.prev; return base; } (longjmp is required wherever signals do not interrupt system calls.) This is really the beginning of a general exception mechanism with protection against stack unwinding, so that routines can clean up after themselves if interrupted (even if the interruption leaps from a low-level routine all the way back to main()). It can be argued that implementing such an exception mechanism using longjmp is a reasonable thing. Indeed, a number of languages provide more direct methods (e.g., Mesa and various Lisps); C provides sufficient primitives, leaving the discipline to use them to the programmer. Now, clearly one can sprinkle `volatile' qualifiers into the declarations in timed_fiddle_with(), so that it will work under pANS C. But (at least some of) the variables so declared are not in fact volatile---the value of `base', in particular, *never changes!* The qualifier is being (mis)used strictly for its side effect of inhibiting optimisation, not because the variable that is so qualified behaves in a way that is not described by the virtual machine. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris