Fix bootstrapping crash.

If a custom small_size2bin table was required due to non-default size
class settings, memory allocation prior to initializing chunk parameters
would cause a crash due to division by 0.  The fix re-orders the various
*_boot() function calls.

Bootstrapping is simpler now than it was before the base allocator
started just using the chunk allocator directly.  This allows
arena_boot[01]() to be combined.

Add error detection for pthread_atfork() and atexit() function calls.
This commit is contained in:
Jason Evans 2010-01-29 14:30:41 -08:00
parent d8f565f239
commit a0bf242230
4 changed files with 30 additions and 22 deletions

View File

@ -412,8 +412,7 @@ void arena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty,
#endif
void *arena_ralloc(void *ptr, size_t size, size_t oldsize);
bool arena_new(arena_t *arena, unsigned ind);
bool arena_boot0(void);
void arena_boot1(void);
bool arena_boot(void);
#endif /* JEMALLOC_H_EXTERNS */
/******************************************************************************/

View File

@ -702,6 +702,15 @@ MALLOC_OUT:
}
}
/* Register fork handlers. */
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork,
jemalloc_postfork) != 0) {
malloc_write4("<jemalloc>", ": Error in pthread_atfork()\n", "",
"");
if (opt_abort)
abort();
}
if (ctl_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);
@ -717,18 +726,25 @@ MALLOC_OUT:
#endif
if (opt_stats_print) {
/* Print statistics at exit. */
atexit(stats_print_atexit);
if (atexit(stats_print_atexit) != 0) {
malloc_write4("<jemalloc>", ": Error in atexit()\n", "",
"");
if (opt_abort)
abort();
}
}
/* Register fork handlers. */
pthread_atfork(jemalloc_prefork, jemalloc_postfork, jemalloc_postfork);
if (chunk_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);
}
if (base_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);
}
if (arena_boot0()) {
if (arena_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);
}
@ -737,12 +753,6 @@ MALLOC_OUT:
tcache_boot();
#endif
if (chunk_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);
}
arena_boot1();
if (huge_boot()) {
malloc_mutex_unlock(&init_lock);
return (true);

View File

@ -2156,8 +2156,9 @@ small_size2bin_init_hard(void)
}
bool
arena_boot0(void)
arena_boot(void)
{
size_t header_size;
/* Set variables according to the value of opt_lg_[qc]space_max. */
qspace_max = (1U << opt_lg_qspace_max);
@ -2214,14 +2215,6 @@ arena_boot0(void)
if (small_size2bin_init())
return (true);
return (false);
}
void
arena_boot1(void)
{
size_t header_size;
/*
* Compute the header size such that it is large enough to contain the
* page map.
@ -2231,4 +2224,6 @@ arena_boot1(void)
arena_chunk_header_npages = (header_size >> PAGE_SHIFT) +
((header_size & PAGE_MASK) != 0);
arena_maxclass = chunksize - (arena_chunk_header_npages << PAGE_SHIFT);
return (false);
}

View File

@ -262,7 +262,11 @@ trace_boot(void)
return (true);
/* Flush trace buffers at exit. */
atexit(malloc_trace_flush_all);
if (atexit(malloc_trace_flush_all) != 0) {
malloc_write4("<jemalloc>", ": Error in atexit()\n", "", "");
if (opt_abort)
abort();
}
/* Receive thread exit notifications. */
if (pthread_key_create(&trace_tsd, trace_thread_cleanup) != 0) {
malloc_write4("<jemalloc>",