@@ -31,36 +31,56 @@ PyNotifier::PyNotifier(std::function<void()> handler) {
31
31
32
32
std::function<void ()> target ([this ] {
33
33
py::gil_scoped_release release;
34
- for (;;) {
35
- int32_t status = 0 ;
36
- HAL_NotifierHandle notifier = m_notifier.load ();
37
- if (notifier == 0 ) {
38
- break ;
39
- }
40
- uint64_t curTime = HAL_WaitForNotifierAlarm (notifier, &status);
41
- if (curTime == 0 || status != 0 ) {
42
- break ;
43
- }
44
34
45
- std::function<void ()> handler;
46
- {
47
- std::scoped_lock lock (m_processMutex);
48
- handler = m_handler;
49
- if (m_periodic) {
50
- m_expirationTime += m_period;
51
- UpdateAlarm ();
52
- } else {
53
- // need to update the alarm to cause it to wait again
54
- UpdateAlarm (UINT64_MAX);
35
+ try {
36
+ for (;;) {
37
+ int32_t status = 0 ;
38
+ HAL_NotifierHandle notifier = m_notifier.load ();
39
+ if (notifier == 0 ) {
40
+ break ;
41
+ }
42
+ uint64_t curTime = HAL_WaitForNotifierAlarm (notifier, &status);
43
+ if (curTime == 0 || status != 0 ) {
44
+ break ;
45
+ }
46
+
47
+ std::function<void ()> handler;
48
+ {
49
+ std::scoped_lock lock (m_processMutex);
50
+ handler = m_handler;
51
+ if (m_periodic) {
52
+ m_expirationTime += m_period;
53
+ UpdateAlarm ();
54
+ } else {
55
+ // need to update the alarm to cause it to wait again
56
+ UpdateAlarm (UINT64_MAX);
57
+ }
58
+ }
59
+
60
+ // call callback
61
+ if (handler) {
62
+ if (Py_IsFinalizing ()) {
63
+ break ;
64
+ }
65
+
66
+ handler ();
55
67
}
56
68
}
69
+ } catch (...) {
70
+ if (Py_IsFinalizing ()) {
71
+ // Hang the thread since returning to the caller is going to crash
72
+ // when we try to obtain the GIL again
73
+ // - this is a daemon thread so it's fine?
74
+ // - Python 3.14 does this too
75
+ while (true ) {}
76
+ }
57
77
58
- // call callback
59
- if (handler)
60
- handler ();
78
+ throw ;
61
79
}
80
+
62
81
if (Py_IsFinalizing ()) {
63
- release.disarm ();
82
+ // see above
83
+ while (true ) {}
64
84
}
65
85
});
66
86
0 commit comments