Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uwm.edu!zaphod.mps.ohio-state.edu!usc!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: Bugs in perl 3.0 pl 8 -- return statement Keywords: registers setjmp(3) random behavior unsafe JMPCLOBBER Message-ID: <7000@jpl-devvax.JPL.NASA.GOV> Date: 6 Feb 90 19:30:58 GMT References: <4080004@hpausla.aso.hp.com> <4080005@hpausla.aso.hp.com> <418@proexam.UUCP> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 80 In article <418@proexam.UUCP> glen@proexam.UUCP (Glen Brydon) writes: : In article <4080005@hpausla.aso.hp.com> brian@hpausla.aso.hp.com (Brian Coogan) writes: : >I just recompiled cmd.c with JMPCLOBBER defined and the bug went away. : >Thanks for your help (especially Paul Maisano who suggested the fix). : >Serves me right for not watching the fixes going by more closely. : : I haven't seen any reply from Larry Wall about this stuff. It concerned : me when Anders Pilegaard posted his alarming article giving rather : mysterious symptoms (non of which I experienced). As he wrote to me: : [message deleted] : : It seems only too clear that my computer and its operating system : should be treated like the cray and those with ANSI compilers. I : will be interested in seeing how Larry deals with this problem in : his upcoming bugfix (#9). Are there systems out there which guarantee : both that the compiler will in fact put your variable in a register : AND that all the registers will be restored as Larry has assumed most : will? Needless to say I have applied a temporary fix and for me this : fixed Brian Coogan's return problem (as it did for him). : : While the gray areas of the language seem to be more interesting to : most people (including me), this stuff scares me to death. Setjmp(3) : seems in fact to be one of those gray areas of UNIX. As I wrote to : Anders Pilegaard, it surprises me the way this particular problem has : been publcized (or not). It is especially confusing then Larry already : anticipated it, but seemed not to realize the danger of his assumptions. : : I hope to see the official fix for this one. There are several things going on here. The first is that there is a bug in cmd.c that hides a statement inside #ifdef JMPCLOBBER that should be outside. These are the statements that say st = stack->ary_array. These are necessary after any expression evaluation because the stack may have been realloced. This has nothing to do with registers. But I believe this is why defining JMPCLOBBER fixed some flakiness. Patch 9 moves these outside the JMPCLOBBER code. Now, as to registers and setjmp/longjmp. We have to distinguish two levels of support here. First, as in the long manual section you quoted, we have machines such as Sun which profess to restore ALL values, but it is indeterminate whether they are restored to their value at setjmp() time or longjmp() time. That's okay, because perl doesn't rely on any variables that could change between the setjmp() and the longjmp(). You shouldn't need JMPCLOBBER on a Sun, at least not if their documentation tells the truth on all Sun architectures. There is a second level of (non-)support here, which is the ANSI level--namely that registers are not guaranteed to have ANY reasonable value after a longjmp(), that is, the value will be neither that at setjmp() time, nor that at longjmp() time. The official solution to this is to declare any variables that you care about as volatile, so that they aren't kept in registers over the setjmp()/longjmp(). Several of you sent me patches to this effect. I don't like the "official" solution. It's overkill. And cmd_exec() is the one routine that can't afford any excess overhead. The routine really wants registers, and much of the routine is outside of setjmp()/longjmp(). So, instead of abandoning the registers, I merely make sure that I have some alternate way of restoring the registers after a longjmp(). This is the code you will find inside of #ifdef JMPCLOBBER. It's unnecessary overhead if registers are restored by longjmp(). The JMPCLOBBER code only adds overhead when entering or exiting a loop or block, because that's the only code that can longjmp. There's one extra statement going in, and two extra going out. And the ones going out are only exercised if the longjmp() actually happens. This has got to be less overhead than abandoning registers altogether. The only problem with it is when to define JMPCLOBBER. It's currently defined on Cray and ANSI C machines. We run the risk of finding a new compiler or machine which isn't ANSI but has ANSI behavior. I think that's a risk I'm willing to take. It may be possible to write a Configure test for it that will usually be right, but it looks hard. For the moment, I'm content to say that if you're on an oddball architecture, and you get flaky results, try defining JMPCLOBBER. I don't think it's something worth panicking about. Larry