Introduce intermediate locking for fork, so that the dynamic linker is
in a consistent state. This most importantly avoids races between dlopen and friends and fork, potentially resulting in dead locks in the child when it itself tries to acquire locks.
This commit is contained in:
parent
4422eacfa3
commit
11954c74b6
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $ */
|
||||
/* $NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $");
|
||||
__RCSID("$NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "namespace.h"
|
||||
@ -48,6 +48,13 @@ __weak_alias(fork, _fork)
|
||||
#endif /* __weak_alias */
|
||||
|
||||
pid_t __fork(void); /* XXX */
|
||||
pid_t __atomic_fork(void) __weak; /* XXX */
|
||||
|
||||
pid_t
|
||||
__atomic_fork(void)
|
||||
{
|
||||
return __fork();
|
||||
}
|
||||
|
||||
struct atfork_callback {
|
||||
SIMPLEQ_ENTRY(atfork_callback) next;
|
||||
@ -157,7 +164,7 @@ fork(void)
|
||||
SIMPLEQ_FOREACH(iter, &prepareq, next)
|
||||
(*iter->fn)();
|
||||
|
||||
ret = __fork();
|
||||
ret = __atomic_fork();
|
||||
|
||||
if (ret != 0) {
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $ */
|
||||
/* $NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1996 John D. Polstra.
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $");
|
||||
__RCSID("$NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -1532,6 +1532,21 @@ __dl_cxa_refcount(void *addr, ssize_t delta)
|
||||
_rtld_exclusive_exit(&mask);
|
||||
}
|
||||
|
||||
pid_t __fork(void);
|
||||
|
||||
__dso_public pid_t
|
||||
__atomic_fork(void)
|
||||
{
|
||||
sigset_t mask;
|
||||
pid_t result;
|
||||
|
||||
_rtld_exclusive_enter(&mask);
|
||||
result = __fork();
|
||||
_rtld_exclusive_exit(&mask);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Error reporting function. Use it like printf. If formats the message
|
||||
* into a buffer, and sets things up so that the next call to dlerror()
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rtld.h,v 1.138 2020/02/29 04:24:33 kamil Exp $ */
|
||||
/* $NetBSD: rtld.h,v 1.139 2020/04/16 14:39:58 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1996 John D. Polstra.
|
||||
@ -370,6 +370,8 @@ __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
|
||||
__dso_public void *_dlauxinfo(void) __pure;
|
||||
__dso_public void __dl_cxa_refcount(void *addr, ssize_t delta);
|
||||
|
||||
__dso_public pid_t __atomic_fork(void);
|
||||
|
||||
#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__)
|
||||
/*
|
||||
* This is used by libgcc to find the start and length of the exception table
|
||||
|
@ -23,5 +23,6 @@
|
||||
___tls_get_addr;
|
||||
__gnu_Unwind_Find_exidx;
|
||||
__dl_cxa_refcount;
|
||||
__atomic_fork;
|
||||
local: *;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user