Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions subprojects/robotpy-wpilib/wpilib/src/rpy/Notifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,56 @@ PyNotifier::PyNotifier(std::function<void()> handler) {

std::function<void()> target([this] {
py::gil_scoped_release release;
for (;;) {
int32_t status = 0;
HAL_NotifierHandle notifier = m_notifier.load();
if (notifier == 0) {
break;
}
uint64_t curTime = HAL_WaitForNotifierAlarm(notifier, &status);
if (curTime == 0 || status != 0) {
break;
}

std::function<void()> handler;
{
std::scoped_lock lock(m_processMutex);
handler = m_handler;
if (m_periodic) {
m_expirationTime += m_period;
UpdateAlarm();
} else {
// need to update the alarm to cause it to wait again
UpdateAlarm(UINT64_MAX);
try {
for (;;) {
int32_t status = 0;
HAL_NotifierHandle notifier = m_notifier.load();
if (notifier == 0) {
break;
}
uint64_t curTime = HAL_WaitForNotifierAlarm(notifier, &status);
if (curTime == 0 || status != 0) {
break;
}

std::function<void()> handler;
{
std::scoped_lock lock(m_processMutex);
handler = m_handler;
if (m_periodic) {
m_expirationTime += m_period;
UpdateAlarm();
} else {
// need to update the alarm to cause it to wait again
UpdateAlarm(UINT64_MAX);
}
}

// call callback
if (handler) {
if (Py_IsFinalizing()) {
break;
}

handler();
}
}
} catch (...) {
if (Py_IsFinalizing()) {
// Hang the thread since returning to the caller is going to crash
// when we try to obtain the GIL again
// - this is a daemon thread so it's fine?
// - Python 3.14 does this too
while(true) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW it looks like CPython's PyThread_hang_thread either sleeps indefinitely or calls the pause syscall, rather than busy looping. Might be worth doing the same here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

}

// call callback
if (handler)
handler();
throw;
}

if (Py_IsFinalizing()) {
release.disarm();
// see above
while(true) {}
}
});

Expand Down
Loading