8000 fix: Infinite recursion when capturing event during serialization (#470) · etherscan-io/sentry-python@a548e4f · GitHub
[go: up one dir, main page]

Skip to content

Commit a548e4f

Browse files
authored
fix: Infinite recursion when capturing event during serialization (getsentry#470)
* fix: Infinite recursion when capturing event during serialization * fix: Actually have "working" repr * fix: Add original test
1 parent ad80fa9 commit a548e4f

File tree

2 files changed

+85
-13
lines changed

2 files changed

+85
-13
lines changed

sentry_sdk/client.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232

3333
_client_init_debug = ContextVar("client_init_debug")
34+
_client_in_capture_event = ContextVar("client_in_capture_event")
3435

3536

3637
def _get_options(*args, **kwargs):
@@ -240,20 +241,29 @@ def capture_event(
240241
241242
:returns: An event ID. May be `None` if there is no DSN set or of if the SDK decided to discard the event for other reasons. In such situations setting `debug=True` on `init()` may help.
242243
"""
243-
if self.transport is None:
244+
is_recursive = _client_in_capture_event.get(False)
245+
if is_recursive:
244246
return None
245-
if hint is None:
246-
hint = {}
247-
rv = event.get("event_id")
248-
if rv is None:
249-
event["event_id"] = rv = uuid.uuid4().hex
250-
if not self._should_capture(event, hint, scope):
251-
return None
252-
event = self._prepare_event(event, hint, scope)
253-
if event is None:
254-
return None
255-
self.transport.capture_event(event)
256-
return rv
247+
248+
_client_in_capture_event.set(True)
249+
250+
try:
251+
if self.transport is None:
252+
return None
253+
if hint is None:
254+
hint = {}
255+
event_id = event.get("event_id")
256+
if event_id is None:
257+
event["event_id"] = event_id = uuid.uuid4().hex
258+
if not self._should_capture(event, hint, scope):
259+
return None
260+
event_opt = self._prepare_event(event, hint, scope)
261+
if event_opt is None:
262+
return None
263+
self.transport.capture_event(event_opt)
264+
return event_id
265+
finally:
266+
_client_in_capture_event.set(False)
257267

258268
def close(
259269
self,

tests/test_client.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,68 @@ def __repr__(self):
560560
)
561561

562562

563+
def test_mapping_sends_exception(sentry_init, capture_events):
564+
sentry_init()
565+
events = capture_events()
566+
567+
class C(Mapping):
568+
def __iter__(self):
569+
try:
570+
1 / 0
571+
except ZeroDivisionError:
572+
capture_exception()
573+
yield "hi"
574+
575+
def __len__(self):
576+
"""List length"""
577+
return 1
578+
579+
def __getitem__(self, ii):
580+
"""Get a list item"""
581+
if ii == "hi":
582+
return "hi"
583+
584+
raise KeyError()
585+
586+
try:
587+
a = C() # noqa
588+
1 / 0
589+
except Exception:
590+
capture_exception()
591+
592+
event, = events
593+
594+
assert event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] == {
595+
"hi": "'hi'"
596+
}
597+
598+
599+
def test_object_sends_exception(sentry_init, capture_events):
600+
sentry_init()
601+
events = capture_events()
602+
603+
class C(object):
604+
def __repr__(self):
605+
try:
606+
1 / 0
607+
except ZeroDivisionError:
608+
capture_exception()
609+
return "hi, i am a repr"
610+
611+
try:
612+
a = C() # noqa
613+
1 / 0
614+
except Exception:
615+
capture_exception()
616+
617+
event, = events
618+
619+
assert (
620+
event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"]
621+
== "hi, i am a repr"
622+
)
623+
624+
563625
def test_errno_errors(sentry_init, capture_events):
564626
sentry_init()
565627
events = capture_events()

0 commit comments

Comments
 (0)
0