@@ -609,7 +609,7 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
609
609
{
610
610
prof_tdata_t * tdata = tctx -> tdata ;
611
611
prof_gctx_t * gctx = tctx -> gctx ;
612
- bool destroy_tdata , destroy_gctx ;
612
+ bool destroy_tdata , destroy_tctx , destroy_gctx ;
613
613
614
614
assert (tctx -> cnts .curobjs == 0 );
615
615
assert (tctx -> cnts .curbytes == 0 );
@@ -622,33 +622,47 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
622
622
malloc_mutex_unlock (tdata -> lock );
623
623
624
624
malloc_mutex_lock (gctx -> lock );
625
- tctx_tree_remove (& gctx -> tctxs , tctx );
626
- if (prof_gctx_should_destroy (gctx )) {
625
+ if (tctx -> state != prof_tctx_state_dumping ) {
626
+ tctx_tree_remove (& gctx -> tctxs , tctx );
627
+ destroy_tctx = true;
628
+ if (prof_gctx_should_destroy (gctx )) {
629
+ /*
630
+ * Increment gctx->nlimbo in order to keep another
631
+ * thread from winning the race to destroy gctx while
632
+ * this one has gctx->lock dropped. Without this, it
633
+ * would be possible for another thread to:
634
+ *
635
+ * 1) Sample an allocation associated with gctx.
636
+ * 2) Deallocate the sampled object.
637
+ * 3) Successfully prof_gctx_try_destroy(gctx).
638
+ *
639
+ * The result would be that gctx no longer exists by the
640
+ * time this thread accesses it in
641
+ * prof_gctx_try_destroy().
642
+ */
643
+ gctx -> nlimbo ++ ;
644
+ destroy_gctx = true;
645
+ } else
646
+ destroy_gctx = false;
647
+ } else {
627
648
/*
628
- * Increment gctx->nlimbo in order to keep another thread from
629
- * winning the race to destroy gctx while this one has
630
- * gctx->lock dropped. Without this, it would be possible for
631
- * another thread to:
632
- *
633
- * 1) Sample an allocation associated with gctx.
634
- * 2) Deallocate the sampled object.
635
- * 3) Successfully prof_gctx_try_destroy(gctx).
636
- *
637
- * The result would be that gctx no longer exists by the time
638
- * this thread accesses it in prof_gctx_try_destroy().
649
+ * A dumping thread needs tctx to remain valid until dumping
650
+ * has finished. Change state such that the dumping thread will
651
+ * complete destruction during a late dump iteration phase.
639
652
*/
640
- gctx -> nlimbo ++ ;
641
- destroy_gctx = true;
642
- } else
653
+ tctx -> state = prof_tctx_state_purgatory ;
654
+ destroy_tctx = false;
643
655
destroy_gctx = false;
656
+ }
644
657
malloc_mutex_unlock (gctx -> lock );
645
658
if (destroy_gctx )
646
659
prof_gctx_try_destroy (tsd , gctx , tdata );
647
660
648
661
if (destroy_tdata )
649
662
prof_tdata_destroy (tsd , tdata , false);
650
663
651
- idalloc (tsd , tctx );
664
+ if (destroy_tctx )
665
+ idalloc (tsd , tctx );
652
666
}
653
667
654
668
static bool
0 commit comments