Discussion:
[Gc] Cygwin and HANDLE_FORK/GC_handle_fork
Erik Bray
2017-03-29 15:26:35 UTC
Permalink
Greetings,

I recently encountered, by way of a bug report in Sage [1], a problem
with using GC in a forked child process on Cygwin. The symptom is an
unhandled SIGABRT issued from within GC_suspend during GC_stop_world
in a child process forked from a process using GC.

I've narrowed this down to a simple test program demonstrating the
problem, attached. The output of a sample run (demonstrating the
issue) looks like:

parent pid: 17500
child pid: 2616
SuspendThread failed

In this case, GC only knows about one thread, the one whose structure
is in the first_thread variable. The problem is that post-fork, the
member first_thread->handle no longer points to a valid HANDLE to any
thread. So when GC_stop_world is hit and it tries to suspend all
threads it knows about, SuspendThread fails and this abort is raised.
This is with GC 7.2 configured with

$ ./configure --enable-threads=posix

This is easily gotten around with the pthread_atexit handlers that are
installed if CAN_HANDLE_FORK is set and the global GC_handle_fork = 1.
This appears to clean up the no longer valid thread struct, so there
are no further errors.

The problem, then, as I see it, is that GC can't work reliably on
Cygwin (in a forking context) *without* HANDLE_FORK--that is,
specifying --enable-handle-fork at configure time. So my proposal is
to enable this feature by default on Cygwin. It works, and I see no
reason *not* to have it.

Thanks,
Erik

[1] https://trac.sagemath.org/ticket/22694
Ivan Maidanski
2017-03-30 22:44:31 UTC
Permalink
Hello Erik,

By default, forking is supported by GC (except for some cases like --enable-munmap on Cygwin) but the client code should inform the GC (at run time) that memory allocations are expected after forking not just exec. This is done by calling GC_set_handle_fork(1) before GC_INIT. In addition, if the client wants parallel marker in the child then it should call GC_start_mark_threads() in the child. (See GC_set_handle_fork and GC_start_mark_threads comment in gc.h for the details.)

Are there obstacles in following this contract in Sage.

The configure --enable-handle-fork option is considered as way to support "legacy" S/W (which was developed when GC_set_handle_fork was not introduced yet).

Regards,
Ivan
Post by Erik Bray
Greetings,
I recently encountered, by way of a bug report in Sage [1], a problem
with using GC in a forked child process on Cygwin. The symptom is an
unhandled SIGABRT issued from within GC_suspend during GC_stop_world
in a child process forked from a process using GC.
I've narrowed this down to a simple test program demonstrating the
problem, attached. The output of a sample run (demonstrating the
parent pid: 17500
child pid: 2616
SuspendThread failed
In this case, GC only knows about one thread, the one whose structure
is in the first_thread variable. The problem is that post-fork, the
member first_thread->handle no longer points to a valid HANDLE to any
thread. So when GC_stop_world is hit and it tries to suspend all
threads it knows about, SuspendThread fails and this abort is raised.
This is with GC 7.2 configured with
 $ ./configure --enable-threads=posix
This is easily gotten around with the pthread_atexit handlers that are
installed if CAN_HANDLE_FORK is set and the global GC_handle_fork = 1.
This appears to clean up the no longer valid thread struct, so there
are no further errors.
The problem, then, as I see it, is that GC can't work reliably on
Cygwin (in a forking context) *without* HANDLE_FORK--that is,
specifying --enable-handle-fork at configure time. So my proposal is
to enable this feature by default on Cygwin. It works, and I see no
reason *not* to have it.
Thanks,
Erik
[1] https://trac.sagemath.org/ticket/22694
_______________________________________________
bdwgc mailing list
https://lists.opendylan.org/mailman/listinfo/bdwgc
Erik Bray
2017-04-11 12:39:43 UTC
Permalink
Thanks for the response.
Post by Ivan Maidanski
Hello Erik,
By default, forking is supported by GC (except for some cases like
--enable-munmap on Cygwin) but the client code should inform the GC (at run
time) that memory allocations are expected after forking not just exec. This
is done by calling GC_set_handle_fork(1) before GC_INIT. In addition, if the
client wants parallel marker in the child then it should call
GC_start_mark_threads() in the child. (See GC_set_handle_fork and
GC_start_mark_threads comment in gc.h for the details.)
Are there obstacles in following this contract in Sage.
Sage doesn't use GC directly. It's used by ECL (Extensible Common
Lisp) which is used by Maxima which is used by Sage...

Everything you say here makes sense to me; I might suggest to the ECL
developers that they use GC_set_handle_fork when initializing GC.
That said....
Post by Ivan Maidanski
The configure --enable-handle-fork option is considered as way to support
"legacy" S/W (which was developed when GC_set_handle_fork was not introduced
yet).
I think the point of my original message was that using GC in a
process that is forked is simply broken on Cygwin without this option,
and causes strange and unexpected application errors (Google seems to
turn up a few more examples of this). So I don't understand why this
wouldn't be enabled by default on that platform.

Thanks,
Erik
Post by Ivan Maidanski
Greetings,
I recently encountered, by way of a bug report in Sage [1], a problem
with using GC in a forked child process on Cygwin. The symptom is an
unhandled SIGABRT issued from within GC_suspend during GC_stop_world
in a child process forked from a process using GC.
I've narrowed this down to a simple test program demonstrating the
problem, attached. The output of a sample run (demonstrating the
parent pid: 17500
child pid: 2616
SuspendThread failed
In this case, GC only knows about one thread, the one whose structure
is in the first_thread variable. The problem is that post-fork, the
member first_thread->handle no longer points to a valid HANDLE to any
thread. So when GC_stop_world is hit and it tries to suspend all
threads it knows about, SuspendThread fails and this abort is raised.
This is with GC 7.2 configured with
$ ./configure --enable-threads=posix
This is easily gotten around with the pthread_atexit handlers that are
installed if CAN_HANDLE_FORK is set and the global GC_handle_fork = 1.
This appears to clean up the no longer valid thread struct, so there
are no further errors.
The problem, then, as I see it, is that GC can't work reliably on
Cygwin (in a forking context) *without* HANDLE_FORK--that is,
specifying --enable-handle-fork at configure time. So my proposal is
to enable this feature by default on Cygwin. It works, and I see no
reason *not* to have it.
Thanks,
Erik
[1] https://trac.sagemath.org/ticket/22694
_______________________________________________
bdwgc mailing list
https://lists.opendylan.org/mailman/listinfo/bdwgc
Loading...