diff --git a/ddtrace/internal/periodic.py b/ddtrace/internal/periodic.py index ad205704f9c..4a4861aac3e 100644 --- a/ddtrace/internal/periodic.py +++ b/ddtrace/internal/periodic.py @@ -56,6 +56,17 @@ def stop(self): def run(self): """Run the target function periodically.""" while not self.quit.wait(self.interval): + # DEV: Some frameworks, like e.g. gevent, seem to resuscitate some + # of the threads that were running prior to the fork of the worker + # processes. These threads are normally created via the native API + # and are exposed to the child process as _DummyThreads. We check + # whether the current thread is no longer an instance of the + # original thread class to prevent it from running in the child + # process while the state copied over from the parent is being + # cleaned up. The restarting of the thread is responsibility to the + # registered forksafe hooks. + if not isinstance(threading.current_thread(), self.__class__): + break self._target() if self._on_shutdown is not None: self._on_shutdown() diff --git a/releasenotes/notes/fix-profiler-gevent-dummy-threads-bfef39da4976aa4b.yaml b/releasenotes/notes/fix-profiler-gevent-dummy-threads-bfef39da4976aa4b.yaml new file mode 100644 index 00000000000..46ac74402c6 --- /dev/null +++ b/releasenotes/notes/fix-profiler-gevent-dummy-threads-bfef39da4976aa4b.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed an issue with gevent worker processes that caused them to crash and + stop.