Subject: Re: [boost] gil::io "non-review" (was: [gil] Can not open test.jpg)
From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2010-03-23 20:41:17
I wonder if anyone will notice this message amid all the mud and
flame-slinging that's going on? I know - I'll get everyone's attention
by pointing out that the fundamental problem here is that the C
library, libjpeg, has a truly awful API design: when it gets an error,
it calls a user-supplied function-pointer and that mustn't return.
Christian Henning wrote:
>> I agree with Phil; that's undefined behaviour. ?I can't access the
>> official C standard here, but in the C99 draft N1256
>> (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf), in
>> 126.96.36.199p2, it says (of longjmp):
>> ... if the function containing
>> the invocation of the setjmp macro has terminated execution in the
>> interim, ... the behavior is undefined.
>> So, once try_something has returned, the effect of calls to longjmp is
> Does that mean I have to call setjmp everytime before I call libjeg
> function? This way the function that calls setjmp would not have been
Your choices are:
1. setjmp() in each function (scope?) that calls into libjpeg. That's
nasty because setjmp(), IIRC, is detected by the compiler and prevents
some optimisations. It's relatively non-intrusive in your code though.
2. setjmp() once, and make sure that that is in a scope that contains
all the calls. This means turning your code inside out, but it's not
impossible because - as we've noted - you never leave a jpeg file open
and return to the user code, i.e. the setjmp() can happen soon after
the user calls into your code. I don't think that destructors will not
be called when longjmp() "pops" the stack, so you need to be careful
about what types you use.
3. (deleted - idea too horrible to share.)
4. Try to throw an exception from the error handler. This would be
ideal, if you could be sure that the exception would propagate through
the C code. I believe that gcc has an option to control that. I have
a feeling that it is enabled for some libraries in Debian precisely to
support this sort of thing. I know nothing about other compilers, and
even on Linux it's probably not reasonable to expect that the user will
use a libjpeg compiled in this way.
5. (Grasping at straws) run libjpeg in a co-routine, err, not sure
exactly how that would work, but something about an extra stack...
6. This is what I'd really like to see: copy the libjpeg source into
your project, and then do (4). You could do some other tidying-up at
the same time.
My recollection is that one of the other libraries also had a setjmp
error handler, but that it could be configured to instead return error
codes while libjpeg can't. Not sure if that's accurate though.