Torsten Förtsch wrote on 2011-05-17:
> On Tuesday, May 10, 2011 21:15:29 Thomas den Braber wrote:
>> In http://www.gossamer-threads.com/lists/modperl/dev/102357 it
>> looks like it is solved.
> 
> Thomas, could you please check if the patch at
> 
>   http://www.gossamer-threads.com/lists/modperl/dev/102983#102983
> 
> fixes your problem? It sounds quite similar. BTW, I have tried to
> reproduce the problem on Linux without success.
> 
> On Tuesday, May 17, 2011 17:27:29 Steve Hay wrote:
>> Any thoughts on whether this change is good to commit?
> 
> Steve, I have tried your patch on my linux box. It passes all tests
> successfully. So, I think go ahead and commit it.
> 
> One thing I don't catch, can this thing happen only in
> mpxs_Apache2__RequestRec_rflush()? I believe it can also happen in all
> the other write operations. If the process crashes on this error I think
> they should also be fixed. Though, without a proper test case it's like
> fishing in murky waters.
> 

Ok, I'll commit that fix shortly.

There are indeed other print / write functions with the same MP_RUN_CROAK check 
in them which will throw an exception if an error (e.g. an aborted connection) 
occurs, but the solution there is to eval { } every print() call in your code 
(tedious if you print() HTML out line by line, but fine if you build up the 
page in memory and only output with a single print() call) and/or have an 
all-encompassing eval round the whole program.

I find it's always a good idea to wrap the whole program in an eval { } to 
catch any problem that might occur, but as long as you have an eval { } at some 
level around the print() call then you're safe. Stas suggested doing that as 
far back as 2005 when the same error was reported: 
http://marc.info/?l=apache-modperl&m=112347961618748&w=2.

And with SVN rev. 1052232 in place you can even now filter out lost connection 
errors and write an error page back in other cases where it is safe to do so.

My point here is that print() failures can (and must be!) caught and handled 
appropriately, whereas the troublesome flush failures seem to happen at a later 
stage and are not caught even by an all-encompassing eval { }, hence mod_perl 
should not be throwing those.

In fact, given that these flush failures apparently can't be caught, perhaps 
flush should never throw an exception? I've changed it so that it just logs 
lost connection errors rather than throwing an exception, but if any other kind 
of error occurs then it will still throw. I've never seen any other cause of 
flush failing in the wild, though, so perhaps if any other kind of error occurs 
then it really is an exceptional situation?

However, since I've also not been able to reproduce the problem myself and 
therefore don't fully understand what is happening, I've taken the approach of 
applying the least changes necessary to fix the problem.

(I even wonder about the whole style of throwing exceptions from the I/O code, 
in particular the PerlIO layer implemented in modperl_io_apache.c: the PerlIO 
manual (perliol.pod) talks of returning NULL or -1 from most functions to 
indicate failure, not throwing exceptions... The downside to that, though, is 
that it forces you to check the return value of every print() call, whereas if 
it throws an exception instead then you can lazily ignore it (it *is* generally 
unlikely to fail, after all), knowing that your all-encompassing eval { } will 
catch it if it does go wrong.)

Reply via email to