Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

At startup, count how many frames adds to tracebacks #634

merged 2 commits into from
Sep 1, 2018
Changes from all commits
File filter

Filter by extension

Filter by extension

Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 36 additions & 8 deletions trio/_core/
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os
import random
import select
import sys
import threading
from collections import deque
Expand Down Expand Up @@ -64,6 +63,34 @@
INSTRUMENT_LOGGER = logging.getLogger("")

# On 3.7+, is implemented in C and doesn't show up in
# tracebacks. On 3.6 and earlier, we use the contextvars backport, which is
# currently implemented in Python and adds 1 frame to tracebacks. So this
# function is a super-overkill version of "0 if sys.version_info >= (3, 7)
# else 1". But if ever changes, we'll be ready!
# This can all be removed once we drop support for 3.6.
def _count_context_run_tb_frames():
def function_with_unique_name_xyzzy():
1 / 0

ctx = copy_context()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this part

except ZeroDivisionError as exc:
tb = exc.__traceback__
# Skip the frame where we caught it
tb = tb.tb_next
count = 0
while tb.tb_frame.f_code.co_name != "function_with_unique_name_xyzzy":
tb = tb.tb_next
count += 1
return count

CONTEXT_RUN_TB_FRAMES = _count_context_run_tb_frames()

class SystemClock:
# Add a large random offset to our clock to ensure that if people
Expand Down Expand Up @@ -1392,13 +1419,14 @@ def run_impl(runner, async_fn, args):
except StopIteration as stop_iteration:
final_result = Value(stop_iteration.value)
except BaseException as task_exc:
# Store for later, removing uninteresting top frames:
# 1. trio._core._run.run_impl()
# 2. (< Python 3.7 only)
tb_next = task_exc.__traceback__.tb_next
if sys.version_info < (3, 7):
belm0 marked this conversation as resolved.
Show resolved Hide resolved
tb_next = tb_next.tb_next
final_result = Error(task_exc.with_traceback(tb_next))
# Store for later, removing uninteresting top frames: 1 frame
# we always remove, because it's this function catching it,
# and then in addition we remove however many more
# adds.
tb = task_exc.__traceback__.tb_next
for _ in range(CONTEXT_RUN_TB_FRAMES):
tb = tb.tb_next
final_result = Error(task_exc.with_traceback(tb))

if final_result is not None:
# We can't call this directly inside the except: blocks above,
Expand Down