[Bug 271490] Deadlock between _rtld_atfork_pre and _thr_attr_init

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 19 May 2023 00:40:21 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271490

--- Comment #2 from KJ Tsanaktsidis <kj@kjtsanaktsidis.id.au> ---
Thanks for your quick eyes.

>  It seems that the problem is that
malloc_mutex_prefork() from jemalloc/src/mutex.c does not lock _all_ jemalloc
mutexes, in particular, the extent mtx.

I guess I could try patching this and see if it makes the deadlocks on my
machine go away. I'll give it a go over the weekend and report back!

> OTOH, note that after fork(), in multi-threaded process child, only async-signal
safe functions are guaranteed to work.

Yeah.... this is unfortunately very common in the Ruby world though, because of
a combination of two things:

* Gems (especially gems by monitoring providers like Datadog, Sentry, NewRelic,
etc) that maintain background threads (to e.g. report metrics & exceptions
asynchronously to some central service)
* Pre-forking webservers (like Unicorn) are frequently used to get good use of
multi-core machines (since only one Ruby thread can run Ruby code at a time).
These webservers often load all of an applications gems, and _then_ fork
workers, to get good use of shared copy-on-write pages.

Most gems that maintain background threads install after_fork hooks to restart
them when they're used inside preforking webservers.

The documentation for fork(2) does say:

> The FreeBSD implementation of fork() provides a usable malloc(3), and rtld(1) services in the child process.

when referring to multi-threaded forks, so I guess _this_ is supposed to work.
I do note however that the man page says nothing about DNS resolution working
in the child of a multithreaded fork :/ but that's a problem for another day
(maybe Ruby ensures that the resolver is not in use before forking? I haven't
looked)

-- 
You are receiving this mail because:
You are the assignee for the bug.