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
Jump to file or symbol
Failed to load files and symbols.
+36 −8
Diff settings

Always

Just for now

Copy path View file
@@ -3,7 +3,6 @@
import os
import random
import select
import sys
import threading
from collections import deque
import collections.abc
@@ -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()

This comment has been minimized.

@belm0

belm0 Aug 28, 2018

Member

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
@@ -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):
This conversation was marked as resolved by belm0

This comment has been minimized.

@belm0

belm0 Aug 28, 2018

Member

I expect that removing this has left an unused import

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,
ProTip! Use n and p to navigate between commits in a pull request.