Skip to content

Commit 93e5585

Browse files
committed
Events: tweak finalization and context references, avoiding calls to dead callbacks.
1 parent 65c6380 commit 93e5585

1 file changed

Lines changed: 30 additions & 1 deletion

File tree

dss_python_backend/events.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import atexit
2+
from weakref import WeakKeyDictionary
13
from .enums import AltDSSEvent
24
from . import ffi, lib
35

@@ -8,7 +10,7 @@
810
)
911

1012
class EventCallbackManager:
11-
_ctx_to_manager = {}
13+
_ctx_to_manager = WeakKeyDictionary()
1214

1315
def __init__(self, ctx):
1416
if ctx in EventCallbackManager._ctx_to_manager:
@@ -19,6 +21,23 @@ def __init__(self, ctx):
1921
for evt_type in AltDSSEvent:
2022
setattr(self, evt_type.name, [])
2123

24+
25+
def unregister_all(self):
26+
for evt_type in AltDSSEvent:
27+
handlers = getattr(self, evt_type.name)
28+
if not handlers:
29+
continue
30+
31+
handlers[:] = []
32+
lib.ctx_DSSEvents_UnregisterAlt(
33+
self.ctx,
34+
evt_type,
35+
lib.altdss_python_util_callback
36+
)
37+
38+
def __del__(self):
39+
self.unregister_all()
40+
2241
def register_func(self, evt: AltDSSEvent, func) -> bool:
2342
handlers = getattr(self, AltDSSEvent(evt).name)
2443
if len(handlers) == 0:
@@ -88,4 +107,14 @@ def altdss_python_util_callback(ctx, eventCode: int, step: int, ptr):
88107
lib.ctx_Error_Set_Description(ctx, f"Python callback exception: {ex}".encode())
89108

90109

110+
def _remove_callbacks():
111+
'''
112+
Remove all callbacks at exit. Since the native library may outlive the Python callbacks,
113+
we need to remove the callbacks here to ensure they are not called.
114+
'''
115+
for ctx_mgr in EventCallbackManager._ctx_to_manager.values():
116+
ctx_mgr.unregister_all()
117+
118+
atexit.register(_remove_callbacks)
119+
91120
__all__ = ['get_manager_for_ctx']

0 commit comments

Comments
 (0)