httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sorin Manolache <sor...@gmail.com>
Subject Re: Module exceptions can be handled before it crashes httpd?
Date Mon, 27 May 2013 09:08:42 GMT
On 2013-05-27 10:30, Sindhi Sindhi wrote:
> Hello,
>
> Is there a way to handle the exceptions (access violation, heap corruption
> etc) thrown by an output filter module within the module itself so that it
> does not propagate till the httpd.exe server resulting in a server crash?
>
> The C++ output filter module that I have written makes use of native memory
> allocation methods like     malloc/new in some cases. I have not used the
> APR request pool here since the allocations in these  methods are very much
> short lived and are called many times within a single request. So rather
> than waiting for the request completion and then the pool manager releasing
> this memory, I'm using native new/delete calls to do the
> allocation/deallocation so that I can release the memory immediately after
> use.
>
> The issue is, in some rare case scenarios I saw a httpd.exe crash that was
> due to heap corruption and access violation during new/delete calls in
> these methods. Is there a way I can gracefully handle these within the
> module by catching such exceptions and trying to handle them, rather
> that propagating this exception resulting in httpd.exe crash?
>
> Worst case even if no filtering happened due to a crash in the module, I'd
> prefer that the filter sent back the original data (that was passed to the
> filter when the filter callback was made by the server) down the filter
> chain, ofcourse after logging this information for later troubleshooting.


Heap corruption/access violation are, most likely, due to bugs in your 
code. These kind of errors are totally different from an out-of-memory 
error, for example. Also they give you a high degree of uncertainty 
about what you're doing and unpredictibility regarding the impacts. It's 
a very bad idea to tolerate them.

If you corrupt some pointers in your structures only, then let us say 
that you could tolerate them, not in principle, as I strongly advise 
against, but at least technically.

However, if you corrupt some pointers in the structures of apache that 
apache reuses for other requests (for example the server_rec, or the 
conf pool, or the array of pointers to module configuration objects), 
then tolerating these kind of errors is impossible, even from a 
technical point of view.

In the first case (when only your structures are corrupt), you could 
catch (at least in Unix) the signal that Unix throws when it detects 
such a violation. But even then your options are limited, because you 
have no idea what you can do without reproducing the violation in the 
violation handler! You can't rely on your data.

(I don't know how these violations are caught in Windows, but I am sure 
they can be caught.)

However, if you corrupted apache's structures, the access violation may 
occur later, not when apache runs your code, but when it runs its code 
or 3rd party code. Then again, in your handler you would not have any 
clue where the violation comes from and how to handle it.


So my advice is to debug your code. Compile it with debug symbols, 
execute it in a debugger, reproduce the scenarios in which it crashes.

If the errors occur only occasionally, then I suspect one of the 
following cases:

*) concurrency problems. To check for this, start running your module at 
low throughput and steadily increase the throughput. If the error rate 
is low at the beginning but increases with throughput, then it could be 
a concurrency problem. You could also start apache with a single thread. 
If it never crashes with a single thread, then again it could be a 
concurrency problem. Check if the libs that you use are thread-safe or not.

*) data-related problem. Run the same request at high throughput. If it 
never crashes, then maybe it is not a concurrency error, but rather 
dependent on the data that you use for testing. So it could be an 
algorithmic problem in your filter.

*) Try to test your corner cases, especially the case is which a string 
to replace is broken between two invocations of the filter. Think of the 
scenario in which the string to replace is contained in _3_ different 
buffers.

Sorin


Mime
View raw message