libes@cme.nist.gov (Don Libes) (09/16/90)
After being bitten by this, I thought about it awhile and I still find it odd. "Portability and the C Language" [Jaeschke] says this is: "so that a call to setjmp directly (which returns 0) cannot be confused with longjmp's returning through setjmp with a value of 0." I think it's more confusing this way. If a programmer doesn't want to be confused with setjmp's original call, then isn't the obvious solution to choose a different value than 0? Why would someone explicitly say longjmp(buf,0) rather than longjmp(buf,1)? It surely can't be for readability! Has any of you personally ever intentionally written longjmp(buf,0) knowing that it would return 1? Or did this become Standard because of "existing practice" and the thought that it would break working programs? (I suspect it would probably fix more programs.) Was there any discussion about "fixing" this? I have some old UNIX manuals that document setjmp returning whatever longjmp says, no questions asked. When did this "feature" creep in? Don Libes libes@cme.nist.gov ...!uunet!cme-durer!libes Oh, and as long as I'm getting my burning questions answered, what does PJ stand for?
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/16/90)
In article <6511@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >Was there any discussion about "fixing" this? I don't recall any, because it not only reflected existing practice, it also is obviously essential to prevent a longjmp from returning to the wrong branch of the setjmp return path. Every version of longjmp I can recall ever maintaining worked exactly that way.
cowan@marob.masa.com (John Cowan) (09/17/90)
In article <13866@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >In article <6511@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >>Was there any discussion about "fixing" this? > >I don't recall any, because it not only reflected existing practice, >it also is obviously essential to prevent a longjmp from returning to >the wrong branch of the setjmp return path. I was bitten by this misfeature once, and had to code around it. The context was that of a complex operation which could succeed, fail, or find resource exhaustion. In the last case, the right thing to do was to retry the entire operation, by which time the exhaustion would have cleared. I attempted to implement SUCCESS as "return", FAILURE as "longjmp(buff,1)" and RETRY as "longjmp(buff,0)". I reasoned that the last case would cause a return to the "setjmp" point before the operation began but with a value of zero, which would cause the operation to begin as if this were the first time. Unfortunately, the operation never got retried! I finally found the relevant line in longjmp(3). Cursing, I recoded RETRY as "longjmp(buff,2)" and changed the setjmp conditional from "if(setjmp(buff)) { main code } else { failure code}" to "if(setjmp(buff) != 1)". I know that the ANS put some restrictions on where you can put setjmp() calls. Is the above legal ANSI C? In other words, can you compare the results of setjmp for non-equality with a constant value? -- cowan@marob.masa.com (aka ...!hombre!marob!cowan) e'osai ko sarji la lojban
guy@auspex.auspex.com (Guy Harris) (09/18/90)
>I don't recall any, because it not only reflected existing practice, >it also is obviously essential to prevent a longjmp from returning to >the wrong branch of the setjmp return path. Even if the person calling "longjmp" screws up and passes a zero argument? It would seem that the prevent this from happening by the simple expedient of not screwing up.... >Every version of longjmp I can recall ever maintaining worked exactly >that way. The BSD one doesn't do that; however, a quick check of the V7 version and the 32V version (from Berkeley's archives, no less) reveals that they seem to have worked the same way as the S5 one, namely that passing a return value of 0 is equivalent to passing a return value of 1. So it looks as if Berkeley are the ones who went off the path, here. Fortunately, the ANSI C spec forbids that sort of thing, so 4.4BSD (and systems that picked up this divergence and haven't yet removed it) will probably get with the program....
libes@cme.nist.gov (Don Libes) (09/18/90)
I asked why setjmp returns 1 after longjmp(buf,0). I got some imaginative answers, only one (below) which struck me as having half a chance of being right. I also did a little research. Yes, I really have all these manuals in front of me as I type this.) V6 didn't have setjmp. It had setexit/reset, neither of which took arguments, and which used a single static buffer. ugh. V7 and 4.0BSD setjmp returned 0 after longjmp(buf,0) (according to the manual). Guy Harris reports that the V7 source shows it returned 1 after longjmp(buf,0). Either my manuals predate his sources, or Berkeley coded from documentation that was incorrect. (Probably both true!) S3 (S4, S5) setjmp returned 1 after longjmp(buf,0). ANSI C setjmp returns 1 after longjmp(buf,0). Some people agreed with me that the Standard behavior is stooopid, while admittedly being existing practice. No one disagreed or claimed this is a useful feature. A few people told me they had also been bitten by this. The responses I suspect are correct are a paraphrase of the self-described "wild guesses" of Karl Heuer <karl@kelp.ima.isc.com> and Scott David Daniels <daniels@cse.ogi.edu>: Often the only information wanted in a setjmp call is whether it is from the initialization or a longjmp. If it had been possible, what would have been defined was "longjmp with one arg causes a non-zero return from the corresponding setjmp; with two args it causes the setjmp to return the second arg." However, as long as longjmp was not treated specially, such semantics were not possible. After the "improvement", programmers didn't have to "bother" with coding the 2nd argument at the price of not being able to return 0. You may find this hard to swallow, but then you probably never passed uncasted 0's either. I think both of these are the mark of thoughtless programming. The end result is that the Standard accepted this behavior without realizing that it was created for a lousy reason. (Yes, I should've complained sooner.) I still claim that no one in their right mind has or ever will write longjmp(buf,0) knowing that it will return 1. What's even more ironic, is that the entire reason for defining it this way (if this theory is correct), is that being able to write "longjmp(buf)" is now illegal! By the way, no one answered my second question either. Although Karl Heuer evidentally knows, he wouldn't tell. >>Oh, and as long as I'm getting my burning questions answered, what >>does PJ stand for? >If you knew, you'd respect his decision to always use his initials. :-) Don Libes libes@cme.nist.gov ...!uunet!cme-durer!libes
rns@se-sd.SanDiego.NCR.COM (Rick Schubert) (09/18/90)
In <6511@muffin.cme.nist.gov> libes@cme.nist.gov (Don Libes) writes: >Oh, and as long as I'm getting my burning questions answered, what >does PJ stand for? Bill. -- Rick Schubert (rns@se-sd.sandiego.NCR.COM)
karl@haddock.ima.isc.com (Karl Heuer) (09/19/90)
In article <4075@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: >So it looks as if Berkeley are the ones who went off the path, here. >Fortunately, the ANSI C spec forbids that sort of thing, so 4.4BSD This is fortunate? Surely a better solution would have been for ANSI to make longjmp(buf,0) undefined behavior instead of guaranteeing the 0->1 kludge. Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
guy@auspex.auspex.com (Guy Harris) (09/20/90)
>>Fortunately, the ANSI C spec forbids that sort of thing, so 4.4BSD > >This is fortunate? It's fortunate that ANSI C is saying *something* about the subject, so that vendors know what they must do and implementors know what they can count on. I don't particular care *what* they say; just about anything will work without too much pain, I don't ever pass "longjmp" a second argument of 0 anyway, and if something that's not ideal in the technical sense is necessary to get consensus, I can live with it.