Skip to content
This repository was archived by the owner on Aug 1, 2022. It is now read-only.

Commit 7fba7d0

Browse files
committed
Fix deadlock on pthread_atfork with glibc >= 2.28 (#31)
pthread_atfork cannot be safely entered from atfork handlers - the behavior is generally deemed as undefined, and while it worked on glibc 2.27 and older, it no longer works since a refactoring in 2.28 to simplify the atfork logic (see https://sourceware.org/git/?p=glibc.git;a=commit;h=27761a1042daf01987e7d79636d0c41511c6df3c). This change may only be safe with glibc (since glibc takes care of reregistering the atfork handlers in the forked process) and additional care may be needed if supporting other libc implementations is desired. Behavior is undefined: https://elias.rhi.hi.is/libc/Threads-and-Fork.html In depth discussion: https://sourceware.org/bugzilla/show_bug.cgi?id=24595#c1 Fix recommendation: https://bugzilla.redhat.com/show_bug.cgi?id=1888660
1 parent f03e3d0 commit 7fba7d0

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

src/posix/manager.c

+26-15
Original file line numberDiff line numberDiff line change
@@ -126,22 +126,8 @@ worker_idle_threshold_per_cpu(void)
126126
return 2;
127127
}
128128

129-
#if !defined(__ANDROID__)
130-
static void
131-
manager_reinit(void)
132-
{
133-
if (manager_init() < 0)
134-
abort();
135-
136-
for (size_t i = 0; i < PTHREAD_WORKQUEUE_MAX; i++) {
137-
wqlist[i] = NULL;
138-
ocwq[i] = NULL;
139-
}
140-
}
141-
#endif
142-
143129
int
144-
manager_init(void)
130+
_manager_init_common(void)
145131
{
146132
wqlist_has_manager = 0;
147133
pthread_cond_init(&wqlist_has_work, NULL);
@@ -183,6 +169,31 @@ manager_init(void)
183169
worker_min = cpu_count > 1 ? cpu_count : 2;
184170
worker_idle_threshold = (PWQ_ACTIVE_CPU > 0) ? (PWQ_ACTIVE_CPU) : worker_idle_threshold_per_cpu();
185171

172+
return (0);
173+
}
174+
175+
#if !defined(__ANDROID__)
176+
static void
177+
manager_reinit(void)
178+
{
179+
if (_manager_init_common() < 0)
180+
abort();
181+
182+
for (size_t i = 0; i < PTHREAD_WORKQUEUE_MAX; i++) {
183+
wqlist[i] = NULL;
184+
ocwq[i] = NULL;
185+
}
186+
}
187+
#endif
188+
189+
int
190+
manager_init(void)
191+
{
192+
int status = _manager_init_common();
193+
if (status != 0) {
194+
return status;
195+
}
196+
186197
/* FIXME: should test for symbol instead of for Android */
187198
#if !defined(__ANDROID__)
188199
if (pthread_atfork(NULL, NULL, manager_reinit) < 0) {

0 commit comments

Comments
 (0)