Fix witness/fork() interactions.
Fix witness to clear its list of owned mutexes in the child if platform-specific malloc_mutex code re-initializes mutexes rather than unlocking them.
This commit is contained in:
parent
174c0c3a9c
commit
108c4a11e9
@ -594,7 +594,8 @@ witness_lock_error
|
|||||||
witness_lockless_error
|
witness_lockless_error
|
||||||
witness_not_owner_error
|
witness_not_owner_error
|
||||||
witness_owner_error
|
witness_owner_error
|
||||||
witness_postfork
|
witness_postfork_child
|
||||||
|
witness_postfork_parent
|
||||||
witness_prefork
|
witness_prefork
|
||||||
witness_unlock
|
witness_unlock
|
||||||
witnesses_cleanup
|
witnesses_cleanup
|
||||||
|
@ -96,7 +96,8 @@ void witness_assert_lockless(tsd_t *tsd);
|
|||||||
void witnesses_cleanup(tsd_t *tsd);
|
void witnesses_cleanup(tsd_t *tsd);
|
||||||
void witness_fork_cleanup(tsd_t *tsd);
|
void witness_fork_cleanup(tsd_t *tsd);
|
||||||
void witness_prefork(tsd_t *tsd);
|
void witness_prefork(tsd_t *tsd);
|
||||||
void witness_postfork(tsd_t *tsd);
|
void witness_postfork_parent(tsd_t *tsd);
|
||||||
|
void witness_postfork_child(tsd_t *tsd);
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_EXTERNS */
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -2770,8 +2770,8 @@ _malloc_prefork(void)
|
|||||||
|
|
||||||
narenas = narenas_total_get();
|
narenas = narenas_total_get();
|
||||||
|
|
||||||
/* Acquire all mutexes in a safe order. */
|
|
||||||
witness_prefork(tsd);
|
witness_prefork(tsd);
|
||||||
|
/* Acquire all mutexes in a safe order. */
|
||||||
ctl_prefork(tsd);
|
ctl_prefork(tsd);
|
||||||
malloc_mutex_prefork(tsd, &arenas_lock);
|
malloc_mutex_prefork(tsd, &arenas_lock);
|
||||||
prof_prefork0(tsd);
|
prof_prefork0(tsd);
|
||||||
@ -2815,6 +2815,7 @@ _malloc_postfork(void)
|
|||||||
|
|
||||||
tsd = tsd_fetch();
|
tsd = tsd_fetch();
|
||||||
|
|
||||||
|
witness_postfork_parent(tsd);
|
||||||
/* Release all mutexes, now that fork() has completed. */
|
/* Release all mutexes, now that fork() has completed. */
|
||||||
chunk_postfork_parent(tsd);
|
chunk_postfork_parent(tsd);
|
||||||
base_postfork_parent(tsd);
|
base_postfork_parent(tsd);
|
||||||
@ -2827,7 +2828,6 @@ _malloc_postfork(void)
|
|||||||
prof_postfork_parent(tsd);
|
prof_postfork_parent(tsd);
|
||||||
malloc_mutex_postfork_parent(tsd, &arenas_lock);
|
malloc_mutex_postfork_parent(tsd, &arenas_lock);
|
||||||
ctl_postfork_parent(tsd);
|
ctl_postfork_parent(tsd);
|
||||||
witness_postfork(tsd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2840,6 +2840,7 @@ jemalloc_postfork_child(void)
|
|||||||
|
|
||||||
tsd = tsd_fetch();
|
tsd = tsd_fetch();
|
||||||
|
|
||||||
|
witness_postfork_child(tsd);
|
||||||
/* Release all mutexes, now that fork() has completed. */
|
/* Release all mutexes, now that fork() has completed. */
|
||||||
chunk_postfork_child(tsd);
|
chunk_postfork_child(tsd);
|
||||||
base_postfork_child(tsd);
|
base_postfork_child(tsd);
|
||||||
@ -2852,7 +2853,6 @@ jemalloc_postfork_child(void)
|
|||||||
prof_postfork_child(tsd);
|
prof_postfork_child(tsd);
|
||||||
malloc_mutex_postfork_child(tsd, &arenas_lock);
|
malloc_mutex_postfork_child(tsd, &arenas_lock);
|
||||||
ctl_postfork_child(tsd);
|
ctl_postfork_child(tsd);
|
||||||
witness_postfork(tsd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -222,8 +222,20 @@ witness_prefork(tsd_t *tsd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
witness_postfork(tsd_t *tsd)
|
witness_postfork_parent(tsd_t *tsd)
|
||||||
{
|
{
|
||||||
|
|
||||||
tsd_witness_fork_set(tsd, false);
|
tsd_witness_fork_set(tsd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
witness_postfork_child(tsd_t *tsd)
|
||||||
|
{
|
||||||
|
#ifndef JEMALLOC_MUTEX_INIT_CB
|
||||||
|
witness_list_t *witnesses;
|
||||||
|
|
||||||
|
witnesses = tsd_witnessesp_get(tsd);
|
||||||
|
ql_new(witnesses);
|
||||||
|
#endif
|
||||||
|
tsd_witness_fork_set(tsd, false);
|
||||||
|
}
|
||||||
|
@ -11,6 +11,13 @@ TEST_BEGIN(test_fork)
|
|||||||
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
p = malloc(64);
|
||||||
|
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
||||||
|
free(p);
|
||||||
|
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
/* Error. */
|
/* Error. */
|
||||||
test_fail("Unexpected fork() failure");
|
test_fail("Unexpected fork() failure");
|
||||||
@ -21,11 +28,23 @@ TEST_BEGIN(test_fork)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Parent. */
|
/* Parent. */
|
||||||
free(p);
|
while (true) {
|
||||||
do {
|
|
||||||
if (waitpid(pid, &status, 0) == -1)
|
if (waitpid(pid, &status, 0) == -1)
|
||||||
test_fail("Unexpected waitpid() failure");
|
test_fail("Unexpected waitpid() failure");
|
||||||
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
if (WIFSIGNALED(status)) {
|
||||||
|
test_fail("Unexpected child termination due to "
|
||||||
|
"signal %d", WTERMSIG(status));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
if (WEXITSTATUS(status) != 0) {
|
||||||
|
test_fail(
|
||||||
|
"Unexpected child exit value %d",
|
||||||
|
WEXITSTATUS(status));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
Loading…
Reference in New Issue
Block a user