Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!rutgers!umd5!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.questions Subject: Re: msleep Message-ID: <9421@mimsy.UUCP> Date: Wed, 18-Nov-87 15:38:50 EST Article-I.D.: mimsy.9421 Posted: Wed Nov 18 15:38:50 1987 Date-Received: Sat, 21-Nov-87 10:53:30 EST References: <332@PT.CS.CMU.EDU> <6060001@hpcupt1.HP.COM> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 84 In article <6060001@hpcupt1.HP.COM> davel@hpcupt1.HP.COM (Dave Lennert) writes: >In reality one would like every system call to accept a signal mask >(like what sigpause() does for pause()). However, it is not impossible >to code reliably; setjmp()...longjmp() work acceptably. Not so. There are two problems here; I shall describe the harder one first. In the presence of longjmp, C needs an unwind-protect mechanism. Example: The 4.3BSD fprintf routine temporarily buffers unbuffered streams. This is often a major performance win, since stderr is normally unbuffered. The problem is illustrated by the code (names changed to protect the innocent): fprintf(FILE *f, ) { unsigned char buf[BUFSIZ]; int ret; int we_buffered_it = 0; if ((f->flags & BUFFERED) == 0) { f->buf = buf; f->bufsize = BUFSIZ; f->flags |= BUFFERED; we_buffered_it = 1; } ret = _doprnt(...); if (we_buffered_it) { f->buf = NULL; f->flags &= ~BUFFERED; } return (ret); } Aside from deferring all signals for the duration of _doprnt() (a bad idea!), there is no way to prevent a longjmp() that leaps out of _doprnt() and fprintf() from trashing FILE *f. With unwind-protect you might do this: unsigned char buf[BUFSIZ]; int ret, omask, we_buffered_it = 0; if ((f->flags & BUFFERED) == 0) { omask = sigblock(ALLSIGS); if (unwind_protect()) { f->buf = NULL; f->flags &= ~BUFFERED; return; /* continue longjmp-ing */ } f->buf = buf; f->bufsize = BUFSIZ; f->flags |= BUFFERED; we_buffered_it = 1; (void) sigsetmask(omask); } ret = _doprnt(...); if (we_buffered_it) { omask = sigblock(ALLSIGS); f->buf = NULL; f->flags &= ~BUFFERED; (void) sigsetmask(omask); } return (ret); The idea is that longjmp() would, as it unwinds stack frames, notice markers left by unwind-protect calls and `return' om there to let the function clean up after itself. Returning from the protection code would resume the longjmp. Back to the easier problem: >In reality one would like every system call to accept a signal mask >(like what sigpause() does for pause()). This also is not true. Any system call that is restarted after a signal does not need a signal mask, simply because having one would make no difference. In this case you *must* use longjmp to abort the system call (which leaves you with the unwind-protect problem above). Adding unwind-protect would fix both problems, actually. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris