This commit is contained in:
Erik Johnston 2019-09-27 15:58:14 +01:00
parent 132279a46f
commit 6374ca40c2

View file

@ -15,7 +15,6 @@
from __future__ import print_function from __future__ import print_function
import inspect
import functools import functools
import sys import sys
@ -32,6 +31,8 @@ def do_patch():
from synapse.logging.context import LoggingContext from synapse.logging.context import LoggingContext
orig_inline_callbacks = defer.inlineCallbacks orig_inline_callbacks = defer.inlineCallbacks
if hasattr(orig_inline_callbacks, "patched_by_synapse"):
return
def new_inline_callbacks(f): def new_inline_callbacks(f):
@functools.wraps(f) @functools.wraps(f)
@ -100,13 +101,20 @@ def do_patch():
return wrapped return wrapped
defer.inlineCallbacks = new_inline_callbacks defer.inlineCallbacks = new_inline_callbacks
new_inline_callbacks.patched_by_synapse = True
def _check_yield_points(f, changes, start_context): def _check_yield_points(f, changes, start_context):
"""Wraps a generator that is about to passed to defer.inlineCallbacks
checking that after every yield the log contexts are correct.
"""
from synapse.logging.context import LoggingContext from synapse.logging.context import LoggingContext
@functools.wraps(f) @functools.wraps(f)
def check_yield_points_inner(*args, **kwargs): def check_yield_points_inner(*args, **kwargs):
expected_context = start_context
gen = f(*args, **kwargs) gen = f(*args, **kwargs)
last_yield_line_no = 1 last_yield_line_no = 1
@ -119,12 +127,13 @@ def _check_yield_points(f, changes, start_context):
else: else:
d = gen.send(result) d = gen.send(result)
except (StopIteration, defer._DefGen_Return) as e: except (StopIteration, defer._DefGen_Return) as e:
if LoggingContext.current_context() != start_context: if LoggingContext.current_context() != expected_context:
# This happens when the context is lost sometime *after* the # This happens when the context is lost sometime *after* the
# final yield and returning. E.g. we forgot to yield on a # final yield and returning. E.g. we forgot to yield on a
# function that returns a deferred. # function that returns a deferred.
err = ( err = (
"%s returned and changed context from %s to %s, in %s between %d and end of func" "Function %r returned and changed context from %s to %s,"
" in %s between %d and end of func"
% ( % (
f.__qualname__, f.__qualname__,
start_context, start_context,
@ -134,7 +143,6 @@ def _check_yield_points(f, changes, start_context):
) )
) )
changes.append(err) changes.append(err)
# print(err, file=sys.stderr)
# raise Exception(err) # raise Exception(err)
return getattr(e, "value", None) return getattr(e, "value", None)
@ -144,10 +152,8 @@ def _check_yield_points(f, changes, start_context):
result = Failure(e) result = Failure(e)
frame = gen.gi_frame frame = gen.gi_frame
if frame.f_code.co_name == "check_yield_points_inner":
frame = inspect.getgeneratorlocals(gen)["gen"].gi_frame
if LoggingContext.current_context() != start_context: if LoggingContext.current_context() != expected_context:
# This happens because the context is lost sometime *after* the # This happens because the context is lost sometime *after* the
# previous yield and *after* the current yield. E.g. the # previous yield and *after* the current yield. E.g. the
# deferred we waited on didn't follow the rules, or we forgot to # deferred we waited on didn't follow the rules, or we forgot to
@ -164,9 +170,10 @@ def _check_yield_points(f, changes, start_context):
) )
) )
changes.append(err) changes.append(err)
# print(err, file=sys.stderr)
# raise Exception(err) # raise Exception(err)
expected_context = LoggingContext.current_context()
last_yield_line_no = frame.f_lineno last_yield_line_no = frame.f_lineno
return check_yield_points_inner return check_yield_points_inner