dev  

Re: Changing the order of cleanup for some core objects

Mladen Turk
Mon, 21 Jul 2008 03:38:58 -0700

Joe Orton wrote:

...
S = apr_socket_create(P)
... do something
... with socket
apr_socket_close(S) -> calls socket_cleanup(S)
...

However if the apr_pool_destroy(P) gets called before
apr_socket_close call (somebody rise the signal, etc..)
the apr_pool_destroy call will cause the socket_cleanup(S)
call and the apr_socket_close(S) will be no-op , and everything
will behave as expected.

1) Any operation on S after P is destroyed has undefined behaviour, including calling apr_socket_close(S). If that doesn't crash and burn with the current implementation it is pure chance.


Sure, and that's the problem. You need to design your
code accordingly so it skips the operations on S if the P was
destroyed by its parent, and that requires maintaining
some sort of operational state info if you bail
out from a blocking call on socket S. You simply
don't have the info about that. This info has to be
maintained in parent pool so that code doesn't touch the
zombie memory still pointed by S (allocated by P), and
that dramatically complicates the user code.


2) No APR function is defined to be async-signal-safe, calling apr_pool_destroy(P) from a signal handler is liable to crash and burn regardless of how you change the cleanup ordering.


Well, hitting CTRL+C shouldn't cause the core :)
I probably wrongly explained the issue. Pool detachment from the parent
is guarded by mutex (I'm here referring to the threaded usage), so
pool can be destroyed asynchronously.

Of course the client code must provide the needed synchronization,
but even with that there is a problem with reverse execution order
of the callbacks; childs are destroyed before or after the cleanup
depending on the initiator. For sockets as an example with pool_destroy
or cleanup case the socket is always hard closed (by invoking its
pool cleanup callback)

I still don't know how to solve that problem effectively, so
any ideas are welcome.


Regards
--
^(TM)