This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: How to make child of failed fork exit cleanly?


On 04/05/2011 5:25 AM, Corinna Vinschen wrote:
On May 3 19:03, Ryan Johnson wrote:
On 03/05/2011 2:41 PM, Corinna Vinschen wrote:
I'm not sure I understand the question.  How do you know which
DLL is already initialized and which isn't?
I'm talking about a call to dll_list::alloc, due to a DLL_LINK which
did not map to its parent's address. At this point we know the fork
has failed and there's no point continuing to try.
[...]
For the moment I've just disabled all finalizers if in_forkee=1, on
the premise that it's better to risk not runing a valid finalizer
than to risk running an invalid one. That made the access violations
go away, [...]
Can't we mark the DLLs in the list for which the constructors ran
successfully and only call them on termination?
I could try that. For some reason before I missed the fact that DLL_LINK state doesn't get copied over until just before the call to load_after_fork, and DLL_LOAD state until after that, so my earlier attempts to selectively disable destructors was broken.

So, two questions come up:

First, when (and where in the code) does the parent's dll list get copied over to the child? My understanding is that Windows makes no promises about what order it runs dll entry points during process startup, so we could conceivably have early-loading dlls start building a dll list from scratch, only to have it clobbered when cygwin1.dll brings the parent's copy across. If so, I cannot trust dll:has_dtors until after all DLL_LINK entry points have been called (in case cygwin1.dll is the last to arrive). I tried poking around in init.cc and dcrt0.cc, but can't find any obvious sign that cygwin dlls which init before cygwin1 would

Actually, if the above happens then it would be very hard to reliably detect dlls whose base address changed...

Meanwhile, I can reverse the sense of has_dtors to destructor calls conditional on (has_dtors != in_forkee). This way it wouldn't matter which version of the list I get and I don't have to complicate code outside dll_init.cc. The downside is the code becomes somewhat more confusing.

Then again, in_forkee never gets cleared if there are no DLL_LOAD around. It's cleared by load_after_fork, which is only called if dll_list::loaded_dlls is non-zero. A quick test with my static-only toy program confirms this (so my current code prevents a statically-linked-only child's finalizers from running even if the fork succeeded... oops).

I can move the in_forkee=false assignment from dll_list::load_after_fork to frok::child, but then the question arises whether to do it before or after the call to ld_preload? Is it possible/legal/meaningful for ld_preload to load a new dll in a forked child?

Ryan


Thoughts? Ryan


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]