mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[hal,wpilib] Fix TimedRobot notifier race (#8445)
It was possible for the alarm to fire between the set alarm and ack, resulting in a hang on next wait. It's not possible to ack before set alarm due to a race in sim step timing, so the fix is to provide an atomic ack and set alarm; the easiest way to implement this in the API was to change ack to optionally also set the alarm again.
This commit is contained in:
@@ -139,14 +139,11 @@ public class TimedRobot extends IterativeRobotBase {
|
||||
// at the end of the loop.
|
||||
var callback = m_callbacks.poll();
|
||||
|
||||
NotifierJNI.setNotifierAlarm(m_notifier, callback.expirationTime, 0, true);
|
||||
|
||||
// Acknowledge previous alarm after setting the next one to avoid a race
|
||||
// against getting the next notifier timeout in HALSIM StepTiming.
|
||||
if (first) {
|
||||
first = false;
|
||||
NotifierJNI.setNotifierAlarm(m_notifier, callback.expirationTime, 0, true);
|
||||
} else {
|
||||
NotifierJNI.acknowledgeNotifierAlarm(m_notifier);
|
||||
NotifierJNI.acknowledgeNotifierAlarm(m_notifier, true, callback.expirationTime, 0, true);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -95,7 +95,7 @@ public class Notifier implements AutoCloseable {
|
||||
}
|
||||
|
||||
// Acknowledge the alarm
|
||||
NotifierJNI.acknowledgeNotifierAlarm(notifier);
|
||||
NotifierJNI.acknowledgeNotifierAlarm(notifier, false, 0, 0, false);
|
||||
}
|
||||
});
|
||||
m_thread.setName("Notifier");
|
||||
|
||||
@@ -120,7 +120,7 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
|
||||
m_watchdogs.remove(this);
|
||||
m_expirationTime = m_startTime + m_timeout;
|
||||
m_watchdogs.add(this);
|
||||
updateAlarm();
|
||||
updateAlarm(false);
|
||||
} finally {
|
||||
m_queueMutex.unlock();
|
||||
}
|
||||
@@ -194,7 +194,7 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
|
||||
m_watchdogs.remove(this);
|
||||
m_expirationTime = m_startTime + m_timeout;
|
||||
m_watchdogs.add(this);
|
||||
updateAlarm();
|
||||
updateAlarm(false);
|
||||
} finally {
|
||||
m_queueMutex.unlock();
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
|
||||
m_queueMutex.lock();
|
||||
try {
|
||||
m_watchdogs.remove(this);
|
||||
updateAlarm();
|
||||
updateAlarm(false);
|
||||
} finally {
|
||||
m_queueMutex.unlock();
|
||||
}
|
||||
@@ -223,9 +223,12 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
private static void updateAlarm() {
|
||||
private static void updateAlarm(boolean acknowledge) {
|
||||
if (m_watchdogs.isEmpty()) {
|
||||
NotifierJNI.cancelNotifierAlarm(m_notifier);
|
||||
} else if (acknowledge) {
|
||||
NotifierJNI.acknowledgeNotifierAlarm(
|
||||
m_notifier, true, (long) (m_watchdogs.peek().m_expirationTime * 1e6), 0, true);
|
||||
} else {
|
||||
NotifierJNI.setNotifierAlarm(
|
||||
m_notifier, (long) (m_watchdogs.peek().m_expirationTime * 1e6), 0, true);
|
||||
@@ -277,9 +280,7 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
|
||||
watchdog.m_callback.run();
|
||||
m_queueMutex.lock();
|
||||
|
||||
updateAlarm();
|
||||
|
||||
NotifierJNI.acknowledgeNotifierAlarm(m_notifier);
|
||||
updateAlarm(true);
|
||||
} finally {
|
||||
m_queueMutex.unlock();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user