This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: How to make child of failed fork exit cleanly?
On 04/05/2011 11:58 AM, Christopher Faylor wrote:
On Wed, May 04, 2011 at 05:33:57PM +0200, Corinna Vinschen wrote:
That said, I've implemented what you suggested (reversing the sense
of dll::has_dtors until fork fixup completes), and it seems to
behave properly. I still wonder, though: can we expect all dlls to
behave properly if (from their perspective) some library they
communicate with has ceased to exist without detaching?
It's a good assumption for a start. If it turns out to be incorrect,
we can take another look.
Wouldn't this do what's required pretty simply?
cgf
--- dll_init.cc 2 May 2011 15:28:34 -0000 1.81
+++ dll_init.cc 4 May 2011 15:57:26 -0000
@@ -37,6 +37,8 @@ static bool dll_global_dtors_recorded;
void
dll_global_dtors ()
{
+ if (in_forkee)
+ return;
int recorded = dll_global_dtors_recorded;
dll_global_dtors_recorded = false;
if (recorded&& dlls.start.next)
Originally I had this (though your way is probably better):
- if (recorded&& dlls.start.next)
+ if (recorded&& dlls.start.next&& !in_forkee)
It also needs (in dll_list::detach):
/* Ensure our exception handler is enabled for destructors */
exception protect;
/* Call finalize function if we are not already exiting */
if (!exit_state)
__cxa_finalize (d);
- d->run_dtors ();
+ if (!in_forkee)
+ d->run_dtors ();
d->prev->next = d->next;
if (d->next)
d->next->prev = d->prev;
I favor one change in dll_init.h instead:
void run_dtors ()
{
- if (has_dtors)
+ if (has_dtors&& !in_forkee)
{
has_dtors = 0;
p.run_dtors ();
}
}
The two problems with the all-or-nothing approach are:
1. in_forkee is only cleared if the parent process had at least one
dynamically loaded dll at fork time (easily resolved by moving it from
dll_list::load_after_fork to just after the call to it from frok::child,
as I mentioned in another email)
2. once frok::child's first call to sync_with_parent returns, the
statically linked dlls are fully initialized and (in theory) need to be
finalized if the process exits. At least, that's the impression I got
from Corinna's response. It does make sense in a way (one might ask why
the finalizers exist if they don't need to run?). However, it's equally
easy to argue that the child doesn't really "exist" until the fork
completes successfully, which I tend to favor given undefined behavior
that would arise if dlls share state with each other. It's easy to
implement either way, though (I've already tested Corinna's suggestion,
it's just a few more lines of code than the above). We just need to
decide which we like better.
Ryan