Move process write part (atfork) to OS layer

Migrates pthread_atfork(3) registration onto the existing os/process.h
dispatcher.
This commit is contained in:
guangli-dai 2026-07-27 17:41:42 -07:00 committed by Guangli Dai
parent 85599c8b12
commit 89b9aef8f7
4 changed files with 55 additions and 7 deletions

View file

@ -14,4 +14,31 @@ os_process_id(void) {
return (int)getpid(); return (int)getpid();
} }
/*
* Shared by every POSIX platform: the four predicates below reproduce, in one
* place, exactly which platforms actually get pthread_atfork() registered.
* - JEMALLOC_HAVE_PTHREAD_ATFORK: the function exists.
* - !JEMALLOC_MUTEX_INIT_CB: on FreeBSD-libthr, _pthread_mutex_init_calloc_cb
* makes libthr's own _malloc_prefork/_malloc_postfork drive the fork
* dance instead. Registering here would be redundant.
* - !JEMALLOC_ZONE: on Darwin, malloc-zone fork callbacks subsume
* pthread_atfork.
* - !__native_client__: Native Client's sandbox doesn't support fork() at
* all, and pthread_atfork() risked being an unresolved symbol in some
* NaCl toolchains. Registering it is both pointless and unsafe there.
*/
JEMALLOC_ALWAYS_INLINE bool
os_process_register_atfork(void (*prepare)(void), void (*parent)(void),
void (*child)(void)) {
#if defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \
&& !defined(JEMALLOC_ZONE) && !defined(__native_client__)
return pthread_atfork(prepare, parent, child) != 0;
#else
(void)prepare;
(void)parent;
(void)child;
return false;
#endif
}
#endif /* JEMALLOC_INTERNAL_OS_POSIX_PROCESS_H */ #endif /* JEMALLOC_INTERNAL_OS_POSIX_PROCESS_H */

View file

@ -11,6 +11,12 @@
/* Functions required for implementation in each backend. */ /* Functions required for implementation in each backend. */
JEMALLOC_ALWAYS_INLINE int os_process_id(void); JEMALLOC_ALWAYS_INLINE int os_process_id(void);
/*
* Install fork handlers, returning true on failure. A no-op returning false
* where fork handler registration doesn't apply.
*/
JEMALLOC_ALWAYS_INLINE bool os_process_register_atfork(
void (*prepare)(void), void (*parent)(void), void (*child)(void));
#if defined(_WIN32) #if defined(_WIN32)
# include "jemalloc/internal/os/windows/process.h" # include "jemalloc/internal/os/windows/process.h"

View file

@ -12,4 +12,14 @@ os_process_id(void) {
return (int)GetCurrentProcessId(); return (int)GetCurrentProcessId();
} }
/* Windows has no fork(2)/pthread_atfork; always a no-op. */
JEMALLOC_ALWAYS_INLINE bool
os_process_register_atfork(void (*prepare)(void), void (*parent)(void),
void (*child)(void)) {
(void)prepare;
(void)parent;
(void)child;
return false;
}
#endif /* JEMALLOC_INTERNAL_OS_WINDOWS_PROCESS_H */ #endif /* JEMALLOC_INTERNAL_OS_WINDOWS_PROCESS_H */

View file

@ -347,13 +347,18 @@ malloc_init_hard_recursible(void) {
} }
} }
#if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \ #ifndef JEMALLOC_MUTEX_INIT_CB
&& !defined(JEMALLOC_ZONE) && !defined(_WIN32) \ /*
&& !defined(__native_client__)) * jemalloc_fork.c names these jemalloc_prefork()/jemalloc_postfork_
/* LinuxThreads' pthread_atfork() allocates. */ * parent() only when !JEMALLOC_MUTEX_INIT_CB; under it they're exported
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, * as _malloc_prefork()/_malloc_postfork() instead (FreeBSD-libthr calls
jemalloc_postfork_child) * those directly, bypassing pthread_atfork() registration entirely --
!= 0) { * see os_process_register_atfork()'s own !JEMALLOC_MUTEX_INIT_CB check).
* Referencing the former names here unconditionally would be a link
* error under JEMALLOC_MUTEX_INIT_CB, since they wouldn't exist.
*/
if (os_process_register_atfork(jemalloc_prefork,
jemalloc_postfork_parent, jemalloc_postfork_child)) {
malloc_write("<jemalloc>: Error in pthread_atfork()\n"); malloc_write("<jemalloc>: Error in pthread_atfork()\n");
if (opt_abort) { if (opt_abort) {
abort(); abort();