g_spawn_async_with_pipes is not thread safe
- From: Andrejs Hanins <andrejs hanins ubnt com>
- To: gtk-devel-list gnome org
- Subject: g_spawn_async_with_pipes is not thread safe
- Date: Fri, 3 Jun 2016 10:46:30 +0300
Hi,
I've discovered a subtle, but quite a serious issue with g_spawn_async_with_pipes API. The problem is
that under some circumstances this API causes memory allocation operations to be called from the forked child
process, which is illegal in multi-threaded environment an may lead to undefined behaviour (I've seen
segfaults and infinite loops in malloc in the child). It happens at least in the following situations:
1. If SPAWN_LEAVE_DESCRIPTORS_OPEN flag is _not_ given, which is often default option, then child (at least
on Linux) does the following call chain fork_exec_with_pipes->do_exec->fdwalk which uses opendir which in
turn uses memory allocation for DIR structure. Some API, like g_spawn_command_line_sync, doesn't allow to
specify flags at all.
2. If script or relative path command is given to execute in a child, then g_execute also uses g_malloc as
seen from the source code. This can't be avoided by flags at all.
3. If child_setup is given by user which also may do some memory operations.
This risky behaviour is not described in the docs and what makes the situation even worse is that although
the application from user point of view may be single-threaded, the usage of, for example, DBus API
implicitly creates an additional dbus thread which does memory allocations, so the application effectively
becomes multi-threaded under the hood.
As I understand, this is hard (maybe even impossible) to fix in a generic way, but at least docs should
explicitly say that this API is not thread safe if SPAWN_LEAVE_DESCRIPTORS_OPEN is not given or
script/relative command is given to be executed or schild_setup uses some mallocs.
I have worked around this bug in my code by using g_spawn_sync with absolute path to a command and setting
also SPAWN_LEAVE_DESCRIPTORS_OPEN flag. My code is glibmm based, but it shouldn't matter at all, because
glibmm is a very thin wrapper around glib APIs in this case.
BR, Andrey
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]