diff --git a/sentry_sdk/sessions.py b/sentry_sdk/sessions.py index a5dd589ee9..2fc4abb407 100644 --- a/sentry_sdk/sessions.py +++ b/sentry_sdk/sessions.py @@ -165,8 +165,9 @@ def __init__( def flush(self): # type: (...) -> None - pending_sessions = self.pending_sessions - self.pending_sessions = [] + with self._thread_lock: + pending_sessions = self.pending_sessions + self.pending_sessions = [] with self._aggregate_lock: pending_aggregates = self.pending_aggregates @@ -190,14 +191,34 @@ def flush(self): if len(envelope.items) > 0: self.capture_func(envelope) + # hygiene: deterministically clean up any stopping thread + if not self._should_join_thread(): + return + with self._thread_lock: + if not self._should_join_thread(): + return + if self._thread: # typing + self._thread.join() + self._thread = None + self._thread_for_pid = None + + def _should_join_thread(self): + # type: (...) -> bool + return ( + not self.__shutdown_requested.is_set() + and self._thread is not None + # we are the parent thread: + and self._thread_for_pid == os.getpid() + ) + def _ensure_running(self): # type: (...) -> None """ Check that we have an active thread to run in, or create one if not. Note that this might fail (e.g. in Python 3.12 it's not possible to - spawn new threads at interpreter shutdown). In that case self._running - will be False after running this function. + spawn new threads at interpreter shutdown). In that case + `__shutdown_requested` will be set after running this function. """ if self._thread_for_pid == os.getpid() and self._thread is not None: return None