You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sys.monitoring: local events still sent after free_tool_id #111963
For now I don't think whether the tool_id is used is checked at all in the instrumentation process. It was only checked on higher level functions like get_events().
It's NOT against the documentation, but I also think it might be better to free all the hooks once the tool_id is freed.
Actually, I'd propose another API sys.monitoring.clear_tool_id() to just clear all the hooks while keeping the tool_id.
However, I believe the reason this is the way it is now, is because instrumentation is lazy-loaded. We don't track all the instrumented code objects and de-instrument them immediately once an event is unset.
Consider the following scenario:
deff():
passsys.monitoring.use_tool_id(1, "tool1")
sys.set_local_events(1, f.__code__, LINE)
sys.monitoring.free_tool_id(1, "tool1")
sys.monitoring.use_tool_id(1, "tool2")
# What would happen here? Does the event fire?
As the instrumentation won't even trigger before f() executes, when f() executes, it'll think tool_id is used - but it's actually already freed once.
In order to achieve that, we may need to put a version number on all events, and on tool_id. That solution might not need a potentially growing piece of memory if the user just toggles tool_id for fun.
Just saying - it's not a trivial issue which we can resolve by adding an if statement somewhere.
Interesting. So it seems fairly straightforward to unregister callbacks, and clear global events, but not to clear local events.
In your example, though, I'd definitely expect neither tool to see the line events on f. I guess I'd be +1 on versioning the set of local events per code object to make that happen.
Actually, global events are lazily instrumented as well. So no that won't work either. Unregister callbacks are easy but that would be even worse if the events are not disabled.
For the version, it would be one version per event (local + global) per code object, plus a version for the tool id. Basically we need to version everything.
Yeah I guess that's why Mark did not do it to begin with. None of the instrumentation commands take effects immediately so the instrumentation need to somehow depend on the current state only.
We can disable the events if the tool_id is not currently used, that's easy, but that just hides the dirt under the carpet. Or we could say that it's the user's responsibility to clean everything up before freeing the id - it's a low level API.
If we do want a clean mechanism, some level of restructure might be needed unless I'm missing something obvious.
I've adapted by holding a WeakSet of the code objects I've set events on, and using it to clear the events when I'm shutting down. This seems to work. At least the documentation could be clearer on this.
Hi @nedbat. We added a clear_tool_id API in #124568 to clear all the callbacks and events (global and local) for a tool_id. Calling free_tool_id will also call that function first so all the registered instrumentation will be reverted. Hope that makes you happy :)
I'll close this issue now because it's really fixed.
Activity
wip: prevent ghost local events
brandtbucher commentedon Nov 10, 2023
Agreed, events should be unset and callbacks should be unregistered when
free_tool_idis called.gaogaotiantian commentedon Nov 10, 2023
For now I don't think whether the tool_id is used is checked at all in the instrumentation process. It was only checked on higher level functions like
get_events().It's NOT against the documentation, but I also think it might be better to free all the hooks once the tool_id is freed.
Actually, I'd propose another API
sys.monitoring.clear_tool_id()to just clear all the hooks while keeping the tool_id.However, I believe the reason this is the way it is now, is because instrumentation is lazy-loaded. We don't track all the instrumented code objects and de-instrument them immediately once an event is unset.
Consider the following scenario:
As the instrumentation won't even trigger before
f()executes, whenf()executes, it'll thinktool_idis used - but it's actually already freed once.In order to achieve that, we may need to put a version number on all events, and on tool_id. That solution might not need a potentially growing piece of memory if the user just toggles tool_id for fun.
Just saying - it's not a trivial issue which we can resolve by adding an if statement somewhere.
brandtbucher commentedon Nov 10, 2023
Interesting. So it seems fairly straightforward to unregister callbacks, and clear global events, but not to clear local events.
In your example, though, I'd definitely expect neither tool to see the line events on
f. I guess I'd be +1 on versioning the set of local events per code object to make that happen.gaogaotiantian commentedon Nov 10, 2023
Actually, global events are lazily instrumented as well. So no that won't work either. Unregister callbacks are easy but that would be even worse if the events are not disabled.
gaogaotiantian commentedon Nov 10, 2023
For the version, it would be one version per event (local + global) per code object, plus a version for the tool id. Basically we need to version everything.
brandtbucher commentedon Nov 10, 2023
Hm, okay. This is definitely harder than it seems.
gaogaotiantian commentedon Nov 10, 2023
Yeah I guess that's why Mark did not do it to begin with. None of the instrumentation commands take effects immediately so the instrumentation need to somehow depend on the current state only.
We can disable the events if the tool_id is not currently used, that's easy, but that just hides the dirt under the carpet. Or we could say that it's the user's responsibility to clean everything up before freeing the id - it's a low level API.
If we do want a clean mechanism, some level of restructure might be needed unless I'm missing something obvious.
wip: prevent ghost local events
nedbat commentedon Nov 11, 2023
I've adapted by holding a WeakSet of the code objects I've set events on, and using it to clear the events when I'm shutting down. This seems to work. At least the documentation could be clearer on this.
29 remaining items
wip: prevent ghost local events
wip: prevent ghost local events
wip: prevent ghost local events
feat(pep669): prevent ghost local events
fix: prevent ghost local events in sysmon
fix: prevent ghost local events in sysmon
fix: prevent ghost local events in sysmon
fix: prevent ghost local events in sysmon
fix: prevent ghost local events in sysmon
fix: prevent ghost local events in sysmon
pythonGH-111963: Clarify sys.monitoring.free_tool_id's limitations (p…
nedbat commentedon Jul 30, 2024
I think this issue can be closed.
pythonGH-111963: Clarify sys.monitoring.free_tool_id's limitations (p…
gaogaotiantian commentedon Oct 1, 2024
Hi @nedbat. We added a
clear_tool_idAPI in #124568 to clear all the callbacks and events (global and local) for atool_id. Callingfree_tool_idwill also call that function first so all the registered instrumentation will be reverted. Hope that makes you happy :)I'll close this issue now because it's really fixed.