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 Context.run adds to tracebacks #634

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions trio/_core/_run.py
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
import collections.abc
Expand Down Expand Up @@ -64,6 +63,34 @@
INSTRUMENT_LOGGER = logging.getLogger("trio.abc.Instrument")


# On 3.7+, Context.run() 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 Context.run 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
Member

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

try:
ctx.run(function_with_unique_name_xyzzy)
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()


@attr.s(frozen=True)
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. contextvars.Context.run() (< 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 Context.run
# 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