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