@@ -350,24 +350,38 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created,
350350 }
351351 background_thread_info_t * info = & background_thread_info [i ];
352352 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
353- if (info -> started ) {
354- pre_reentrancy (tsd );
355- int err = pthread_create_wrapper (& info -> thread , NULL ,
356- background_thread_entry , (void * )(uintptr_t )i );
357- post_reentrancy (tsd );
358-
359- if (err == 0 ) {
360- (* n_created )++ ;
361- created_threads [i ] = true;
362- } else {
363- malloc_printf ("<jemalloc>: background thread "
364- "creation failed (%d)\n" , err );
365- if (opt_abort ) {
366- abort ();
367- }
353+
354+ bool create = info -> started ;
355+ malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
356+ if (!create ) {
357+ continue ;
358+ }
359+
360+ /*
361+ * To avoid deadlock with prefork handlers (which waits for the
362+ * mutex held here), unlock before calling pthread_create().
363+ */
364+ malloc_mutex_unlock (tsd_tsdn (tsd ),
365+ & background_thread_info [0 ].mtx );
366+ pre_reentrancy (tsd );
367+ int err = pthread_create_wrapper (& info -> thread , NULL ,
368+ background_thread_entry , (void * )(uintptr_t )i );
369+ post_reentrancy (tsd );
370+ malloc_mutex_lock (tsd_tsdn (tsd ),
371+ & background_thread_info [0 ].mtx );
372+
373+ if (err == 0 ) {
374+ (* n_created )++ ;
375+ created_threads [i ] = true;
376+ } else {
377+ malloc_printf ("<jemalloc>: background thread "
378+ "creation failed (%d)\n" , err );
379+ if (opt_abort ) {
380+ abort ();
368381 }
369382 }
370- malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
383+ /* Since we unlocked and may miss signals, restart. */
384+ i = 1 ;
371385 }
372386}
373387
@@ -643,14 +657,7 @@ background_thread_interval_check(tsdn_t *tsdn, arena_t *arena,
643657void
644658background_thread_prefork0 (tsdn_t * tsdn ) {
645659 malloc_mutex_prefork (tsdn , & background_thread_lock );
646- if (background_thread_enabled ()) {
647- background_thread_enabled_at_fork = true;
648- background_thread_enabled_set (tsdn , false);
649- background_threads_disable (tsdn_tsd (tsdn ));
650- } else {
651- background_thread_enabled_at_fork = false;
652- }
653- assert (n_background_threads == 0 );
660+ background_thread_enabled_at_fork = background_thread_enabled ();
654661}
655662
656663void
@@ -660,22 +667,12 @@ background_thread_prefork1(tsdn_t *tsdn) {
660667 }
661668}
662669
663- static void
664- background_thread_postfork_init (tsdn_t * tsdn ) {
665- assert (n_background_threads == 0 );
666- if (background_thread_enabled_at_fork ) {
667- background_thread_enabled_set (tsdn , true);
668- background_threads_enable (tsdn_tsd (tsdn ));
669- }
670- }
671-
672670void
673671background_thread_postfork_parent (tsdn_t * tsdn ) {
674672 for (unsigned i = 0 ; i < ncpus ; i ++ ) {
675673 malloc_mutex_postfork_parent (tsdn ,
676674 & background_thread_info [i ].mtx );
677675 }
678- background_thread_postfork_init (tsdn );
679676 malloc_mutex_postfork_parent (tsdn , & background_thread_lock );
680677}
681678
@@ -686,9 +683,23 @@ background_thread_postfork_child(tsdn_t *tsdn) {
686683 & background_thread_info [i ].mtx );
687684 }
688685 malloc_mutex_postfork_child (tsdn , & background_thread_lock );
686+ if (!background_thread_enabled_at_fork ) {
687+ return ;
688+ }
689689
690+ /* Clear background_thread state (reset to disabled for child). */
690691 malloc_mutex_lock (tsdn , & background_thread_lock );
691- background_thread_postfork_init (tsdn );
692+ n_background_threads = 0 ;
693+ background_thread_enabled_set (tsdn , false);
694+ for (unsigned i = 0 ; i < ncpus ; i ++ ) {
695+ background_thread_info_t * info = & background_thread_info [i ];
696+ malloc_mutex_lock (tsdn , & info -> mtx );
697+ info -> started = false;
698+ int ret = pthread_cond_init (& info -> cond , NULL );
699+ assert (ret == 0 );
700+ background_thread_info_init (tsdn , info );
701+ malloc_mutex_unlock (tsdn , & info -> mtx );
702+ }
692703 malloc_mutex_unlock (tsdn , & background_thread_lock );
693704}
694705
0 commit comments