Re[2]: [Gc] Re: Problem pthread_atfork

Ivan Maidanski ivmai at mail.ru
Tue Mar 27 05:48:41 PST 2012


Hi Andy and Hans,

Hans -
Please expression your opinion.

Tue, 27 Mar 2012 13:38:38 +0200 Andy Wingo <wingo at pobox.com>:
> Hi Ivan,
> 
> On Tue 27 Mar 2012 10:23, Ivan Maidanski <ivmai at mail.ru> writes:
> 
> > Mon, 26 Mar 2012 18:55:43 +0200 Andy Wingo <wingo at pobox.com>:
> >> On Mon 26 Mar 2012 14:59, Ivan Maidanski <ivmai at mail.ru> writes:
> >> 
> >> > 1. provide configure --enable/disable-handle-fork trigging
> [NO_]HANDLE_FORK
> >> 
> >> Sure, will do.
> >
> > Thanks. Although it is ok to pass it via CFLAGS, --enable-x is more uniform
> way.
> 
> Attached.  I leave it to you to regenerate the autofoo; I think we have
> different versions.
> 
> > Another solution is to let the client decide whether fork should be handled
> by GC at runtime (in case the client rely on memory allocation after fork)?
> > (E.g., export GC_fork_prepare/parent/child_proc).
> >
> > Yet more solution is to redirect fork to GC_fork (which calls prepare, fork,
> parent/child). Looks to me the best way.
> > Your opinion?
> 
> I think that if libgc is to handle multithreaded fork, it needs to use
> pthread_atfork and not some other API.  This is to ensure a consistent
> locking order (at fork-time) between libgc, the libraries it uses
> (e.g. libc), and the libraries that use it.  There can only be one
> locking order, and thus one pthread_atfork.

This is unclear to me. If the client code is:

GC_fork_prepare_proc();
pid = fork();
if (pid) {
 GC_fork_parent_proc();
} else {
 GC_fork_child_proc();
}

Is the correct locking order ensured here or not?

In case we aren't intercepting fork, we could export these 3 routines (if GC_THREADS) removing atfork call in GC itself and the client is free to:
1. not use them since no fork (or no memory alloc in child)
2. call pthread_atfork(GC_...) beforehand (if atfork available)
3. use the above code snippet (provided pthread_atfork(GC_...) has not been called)
4. rebuild GC with -D HANDLE_FORK (in this case export GC_fork_X_proc should be no-op).

Looks to be flexible.

> 
> >> If I may suggest, perhaps the right thing to do is not enable this code
> >> by default, as it makes otherwise correct programs incorrect.  That is,
> >> for a program that only calls signal-safe primitives after a
> >> multi-threaded fork, this patch makes such a program depend on
> >> unspecified behavior of their OS.
> >
> > I don't see: where is unspecified behavior if atfork is available? (we
> > just adjust some global vars in GC at fork).
> 
> The client calls the following functions that are not async-signal-safe
> from within the child atfork handler:
> 
> mach_thread_self
> pthread_setspecific
> pthread_getspecific
> pthread_mutex_lock
> pthread_mutex_unlock
> pthread_setcancelstate

Ok. Now I see.

> 
> More broadly though, does it make sense to allocate memory at all after
> a multi-threaded fork?  The collector as a whole is not
> async-signal-safe, so installing pthread_atfork() handlers does not
> enable users to create correct programs.
> 
> I realize that the reality of the situation is that things will probably
> work.  Libc installs atfork handlers for most of its data structures
> (though not all).  But it's not something that is guaranteed to work, so
> I'm not planning to make programs assuming that I can use the collector
> after a multi-threaded fork.

I've looked into Android: it does not offer pthread_atfork but it uses fork to clone Zygote process (Dalvik VM continues to work in child without exec).

> 
> Regards,
> Andy
> -- 
> http://wingolog.org/



More information about the Gc mailing list