Re: g_spawn_async_with_pipes is not thread safe
- Date: Fri, 3 Jun 2016 15:14:38 +0300
- From: Andrejs Hanins <andrejs.hanins@xxxxxxxx>
- Subject: Re: g_spawn_async_with_pipes is not thread safe
On 06/03/2016 02:30 PM, Simon McVittie wrote:
> On 03/06/16 09:18, Chris Vine wrote:
>> POSIX allows only async-signal-safe functions (see signal(7)) to be
>> called in the child between fork() and exec(), which drastically limits
>> the usefulness of child setup functions
> There's a gap here between the theory (GLib mostly has only POSIX
> requirements) and the practice (glibc malloc is designed to allow things
> POSIX doesn't, and this useful functionality would be difficult to
> achieve without that).
That explains everything. Originally I had crashes/hangs under OpenWrt
and musl as libc. I should have said that in my first email. Then I switched
to desktop Linux with glibc for testing and also got hangs in a forked child,
but it was actually due to rand() which I used to get random memory
allocation sizes. rand() uses __libc_lock_lock which is apparently not fork
safe. After removing rand() and leaving only malloc/free in parent/child I
wasn't able to reproduce the problem. In the same time, the same code
on OpenWrt with musl hangs just after few seconds. So you are right -
glibc does more than POSIX requires, but musl doesn't.
So this is strictly speaking not a musl bug, because it is POSIX compliant.
>From the other side, glib code seems to be dependant on the fact that
underlying glibc memory allocation functions are so to say fork-safe which
is not a POSIX requirement.
Am I right in my conclusions? If yes, then what is the right way to address
the problem - mention in docs that spawning glib API is not safe if your
underlying libc is not fork-safe? Doh :(
> In principle GLib could call opendir() on
> /proc/$pid before forking, then read it in the child, but readdir()
> isn't async-signal-safe either. Doing the reading in the parent isn't a
> solution, because the parent is potentially multi-threaded, so it could
> be opening and closing file descriptors in other threads (racing with
> the readdir()).
> In principle the parent could read the new child's fd table and write a
> list of fds into a pipe, for the child to close them all or set them all
> close-on-exec, while the child waits for EOF on that pipe before
> proceeding with the close and exec operations... but that seems fairly
> I think what we really want here is *BSD closefrom(), which at least
> FreeBSD documents as async-signal-safe. Unfortunately, Linux doesn't
> have that system call. libdbus would have the same issue on platforms
> that don't have closefrom().
gtk-devel-list mailing list