@@ -581,6 +581,9 @@ cdef class ProfileFunctionGuard:
581
581
NativeTracker.forgetPythonStack()
582
582
583
583
584
+ tracker_creation_lock = threading.Lock()
585
+
586
+
584
587
cdef class Tracker:
585
588
""" Context manager for tracking memory allocations in a Python script.
586
589
@@ -690,46 +693,48 @@ cdef class Tracker:
690
693
691
694
@ cython.profile (False )
692
695
def __enter__ (self ):
693
- if NativeTracker.getTracker() != NULL :
694
- raise RuntimeError (" No more than one Tracker instance can be active at the same time" )
695
-
696
696
cdef unique_ptr[RecordWriter] writer
697
- if self ._writer == NULL :
698
- raise RuntimeError (" Attempting to use stale output handle" )
699
- writer = move(self ._writer)
700
-
701
- for attr in (" _name" , " _ident" ):
702
- assert not hasattr (threading.Thread, attr)
703
- setattr (
704
- threading.Thread,
705
- attr,
706
- ThreadNameInterceptor(attr, NativeTracker.registerThreadNameById),
707
- )
697
+ with tracker_creation_lock:
698
+ if NativeTracker.getTracker() != NULL :
699
+ raise RuntimeError (" No more than one Tracker instance can be active at the same time" )
700
+
701
+ if self ._writer == NULL :
702
+ raise RuntimeError (" Attempting to use stale output handle" )
703
+ writer = move(self ._writer)
704
+
705
+ for attr in (" _name" , " _ident" ):
706
+ assert not hasattr (threading.Thread, attr)
707
+ setattr (
708
+ threading.Thread,
709
+ attr,
710
+ ThreadNameInterceptor(attr, NativeTracker.registerThreadNameById),
711
+ )
708
712
709
- self ._previous_profile_func = sys.getprofile()
710
- self ._previous_thread_profile_func = threading._profile_hook
711
- threading.setprofile(start_thread_trace)
713
+ self ._previous_profile_func = sys.getprofile()
714
+ self ._previous_thread_profile_func = threading._profile_hook
715
+ threading.setprofile(start_thread_trace)
712
716
713
- if " greenlet" in sys.modules:
714
- NativeTracker.beginTrackingGreenlets()
717
+ if " greenlet" in sys.modules:
718
+ NativeTracker.beginTrackingGreenlets()
715
719
716
- NativeTracker.createTracker(
717
- move(writer),
718
- self ._native_traces,
719
- self ._memory_interval_ms,
720
- self ._follow_fork,
721
- self ._trace_python_allocators,
722
- )
723
- return self
720
+ NativeTracker.createTracker(
721
+ move(writer),
722
+ self ._native_traces,
723
+ self ._memory_interval_ms,
724
+ self ._follow_fork,
725
+ self ._trace_python_allocators,
726
+ )
727
+ return self
724
728
725
729
@ cython.profile (False )
726
730
def __exit__ (self , exc_type , exc_value , exc_traceback ):
727
- NativeTracker.destroyTracker()
728
- sys.setprofile(self ._previous_profile_func)
729
- threading.setprofile(self ._previous_thread_profile_func)
731
+ with tracker_creation_lock:
732
+ NativeTracker.destroyTracker()
733
+ sys.setprofile(self ._previous_profile_func)
734
+ threading.setprofile(self ._previous_thread_profile_func)
730
735
731
- for attr in (" _name" , " _ident" ):
732
- delattr (threading.Thread, attr)
736
+ for attr in (" _name" , " _ident" ):
737
+ delattr (threading.Thread, attr)
733
738
734
739
735
740
def start_thread_trace (frame , event , arg ):
0 commit comments