-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-118415: Fix issues with local tracing being enabled/disabled on a function #118496
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
Conversation
Python/instrumentation.c
Outdated
static inline | ||
int debug_check_sanity(PyInterpreterState *interp, PyCodeObject *code) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static inline | |
int debug_check_sanity(PyInterpreterState *interp, PyCodeObject *code) | |
static int | |
debug_check_sanity(PyInterpreterState *interp, PyCodeObject *code) |
@@ -227,6 +218,29 @@ def test_register_callback(self): | |||
for ref in self.refs: | |||
self.assertEqual(ref(), None) | |||
|
|||
def test_set_local_trace_opcodes(self): | |||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return
here doesn't look right
with l: | ||
pass | ||
|
||
t = threading.Thread(target=f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing import threading
or t = Thread(target=f)
Python/instrumentation.c
Outdated
for (int i = 0; i < code_len; i++) { | ||
code->_co_monitoring->per_instruction_tools[i] = 0; | ||
int opcode = _PyCode_CODE(code)[i].op.code; | ||
code->_co_monitoring->per_instruction_tools[i] = _PyOpcode_Deopt[opcode]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look right. Shouldn't it be initialized to zero?
Python/instrumentation.c
Outdated
@@ -1000,7 +1000,7 @@ instrumentation_cross_checks(PyInterpreterState *interp, PyCodeObject *code) | |||
return monitors_equals(code->_co_monitoring->active_monitors, expected); | |||
} | |||
|
|||
static inline | |||
static |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My previously comment was mostly intended to be that static int
should be on one line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I'd fix the formatting of debug_check_sanity
When tracing is getting enabled / disabled locally we are currently updating the per-instruction-tools and per-line-tools, either clearing or restoring the non-optimized opcodes that we should fall back to.
When another thread is executing it may see the instrumented opcode and then race with the events and then not see the original opcode as tracing may have changed.
This changes it so that we just always maintain the original opcodes for all of the instructions. It means we can't do some sanity checks but the fact that it's not changing simplifies things.
There's also some assertions that can fire because the local events are being enabled or disabled. At runtime these races are benign, we're just delivering events on other threads in a short window after tracing is disabled or not delivering events in a short window after it's enabled. But the asserts need to lock the code object to be able to get a consistent view on the world.