@@ -783,3 +783,39 @@ def before_send_log(log, _):
783783 )
784784
785785 get_client ().flush ()
786+
787+
788+ @minimum_python_37
789+ @pytest .mark .timeout (5 )
790+ def test_reentrant_add_does_not_deadlock (sentry_init , capture_envelopes ):
791+ """Adding to the batcher from within a flush must not deadlock.
792+
793+ This covers the scenario where GC emits a ResourceWarning during
794+ _add_to_envelope (or _flush_event.wait/set), and the warning is
795+ routed through the logging integration back into batcher.add().
796+ See https://github.com/getsentry/sentry-python/issues/5681
797+ """
798+ sentry_init (enable_logs = True )
799+ capture_envelopes ()
800+
801+ client = sentry_sdk .get_client ()
802+ batcher = client .log_batcher
803+
804+ reentrant_add_called = False
805+ original_add_to_envelope = batcher ._add_to_envelope
806+
807+ def add_to_envelope_with_reentrant_add (envelope ):
808+ nonlocal reentrant_add_called
809+ # Simulate a GC warning routing back into add() during flush
810+ batcher .add ({"fake" : "log" })
811+ reentrant_add_called = True
812+ original_add_to_envelope (envelope )
813+
814+ batcher ._add_to_envelope = add_to_envelope_with_reentrant_add
815+
816+ sentry_sdk .logger .warning ("test log" )
817+ client .flush ()
818+
819+ assert reentrant_add_called
820+ # If the re-entrancy guard didn't work, this test would hang and it'd
821+ # eventually be timed out by pytest-timeout
0 commit comments