Skip to content

Commit f27a714

Browse files
authored
Merge pull request #151 from robotpy/safer-notifier
Notifier: prevent SIGABRT when program exits
2 parents fce6875 + ee7289b commit f27a714

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

subprojects/robotpy-wpilib/wpilib/src/rpy/Notifier.cpp

+44-24
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,56 @@ PyNotifier::PyNotifier(std::function<void()> handler) {
3131

3232
std::function<void()> target([this] {
3333
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-
}
4434

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();
5567
}
5668
}
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+
}
5777

58-
// call callback
59-
if (handler)
60-
handler();
78+
throw;
6179
}
80+
6281
if (Py_IsFinalizing()) {
63-
release.disarm();
82+
// see above
83+
while(true) {}
6484
}
6585
});
6686

0 commit comments

Comments
 (0)