Make HAL_Initialize timeout configurable, makes result a bool, and makes Java an exception rather than assert. (#557)

This commit is contained in:
Thad House
2017-07-01 00:43:06 -07:00
committed by Peter Johnson
parent d34c844900
commit 2da26c0579
7 changed files with 66 additions and 50 deletions

View File

@@ -68,7 +68,7 @@ HAL_PortHandle HAL_GetPortWithModule(int32_t module, int32_t channel);
uint64_t HAL_GetFPGATime(int32_t* status);
int32_t HAL_Initialize(int32_t mode);
HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode);
// ifdef's definition is to allow for default parameters in C++.
#ifdef __cplusplus

View File

@@ -287,15 +287,61 @@ void HAL_BaseInitialize(int32_t* status) {
initialized = true;
}
static bool killExistingProgram(int timeout, int mode) {
// Kill any previous robot programs
std::fstream fs;
// By making this both in/out, it won't give us an error if it doesnt exist
fs.open("/var/lock/frc.pid", std::fstream::in | std::fstream::out);
if (fs.bad()) return false;
pid_t pid = 0;
if (!fs.eof() && !fs.fail()) {
fs >> pid;
// see if the pid is around, but we don't want to mess with init id=1, or
// ourselves
if (pid >= 2 && kill(pid, 0) == 0 && pid != getpid()) {
llvm::outs() << "Killing previously running FRC program...\n";
kill(pid, SIGTERM); // try to kill it
std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
if (kill(pid, 0) == 0) {
// still not successfull
if (mode == 0) {
llvm::outs() << "FRC pid " << pid << " did not die within " << timeout
<< "ms. Aborting\n";
return 0; // just fail
} else if (mode == 1) { // kill -9 it
kill(pid, SIGKILL);
} else {
llvm::outs() << "WARNING: FRC pid " << pid << " did not die within "
<< timeout << "ms.\n";
}
}
}
}
fs.close();
// we will re-open it write only to truncate the file
fs.open("/var/lock/frc.pid", std::fstream::out | std::fstream::trunc);
fs.seekp(0);
pid = getpid();
fs << pid << std::endl;
fs.close();
return true;
}
/**
* Call this to start up HAL. This is required for robot programs.
*/
int32_t HAL_Initialize(int32_t mode) {
HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
setlinebuf(stdin);
setlinebuf(stdout);
prctl(PR_SET_PDEATHSIG, SIGTERM);
// Return false if program failed to kill an existing program
if (!killExistingProgram(timeout, mode)) {
return false;
}
FRC_NetworkCommunication_Reserve(nullptr);
std::atexit([]() {
@@ -311,52 +357,21 @@ int32_t HAL_Initialize(int32_t mode) {
timerRollover, nullptr, &status);
if (status == 0) {
uint64_t curTime = HAL_GetFPGATime(&status);
if (status == 0)
if (status == 0) {
HAL_UpdateNotifierAlarm(rolloverNotifier, curTime + 0x80000000ULL,
&status);
}
// Kill any previous robot programs
std::fstream fs;
// By making this both in/out, it won't give us an error if it doesnt exist
fs.open("/var/lock/frc.pid", std::fstream::in | std::fstream::out);
if (fs.bad()) return 0;
pid_t pid = 0;
if (!fs.eof() && !fs.fail()) {
fs >> pid;
// see if the pid is around, but we don't want to mess with init id=1, or
// ourselves
if (pid >= 2 && kill(pid, 0) == 0 && pid != getpid()) {
llvm::outs() << "Killing previously running FRC program...\n";
kill(pid, SIGTERM); // try to kill it
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (kill(pid, 0) == 0) {
// still not successfull
if (mode == 0) {
llvm::outs() << "FRC pid " << pid
<< " did not die within 110ms. Aborting\n";
return 0; // just fail
} else if (mode == 1) { // kill -9 it
kill(pid, SIGKILL);
} else {
llvm::outs() << "WARNING: FRC pid " << pid
<< " did not die within 110ms.\n";
}
}
} else {
// return false if status failed.
return false;
}
} else {
// return false if status failed.
return false;
}
fs.close();
// we will re-open it write only to truncate the file
fs.open("/var/lock/frc.pid", std::fstream::out | std::fstream::trunc);
fs.seekp(0);
pid = getpid();
fs << pid << std::endl;
fs.close();
HAL_InitializeDriverStation();
return 1;
return true;
}
int64_t HAL_Report(int32_t resource, int32_t instanceNumber, int32_t context,

View File

@@ -19,7 +19,7 @@ class DriverStation;
#define START_ROBOT_CLASS(_ClassName_) \
int main() { \
if (!HAL_Initialize(0)) { \
if (!HAL_Initialize(500, 0)) { \
llvm::errs() << "FATAL ERROR: HAL could not be initialized\n"; \
return -1; \
} \

View File

@@ -26,7 +26,7 @@ class TestEnvironment : public testing::Environment {
if (m_alreadySetUp) return;
m_alreadySetUp = true;
if (!HAL_Initialize(0)) {
if (!HAL_Initialize(500, 0)) {
llvm::errs() << "FATAL ERROR: HAL could not be initialized\n";
std::exit(-1);
}

View File

@@ -34,11 +34,11 @@ extern "C" {
/*
* Class: edu_wpi_first_wpilibj_hal_HAL
* Method: Initialize
* Signature: (I)I
* Signature: (Z)II
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_wpilibj_hal_HAL_initialize(JNIEnv*, jclass, jint mode) {
return HAL_Initialize(mode);
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_wpilibj_hal_HAL_initialize(JNIEnv*, jclass, jint timeout, jint mode) {
return HAL_Initialize(timeout, mode);
}
/*

View File

@@ -168,8 +168,9 @@ public abstract class RobotBase {
* Common initialization for all robot programs.
*/
public static void initializeHardwareConfiguration() {
int rv = HAL.initialize(0);
assert rv == 1;
if (!HAL.initialize(500, 0)) {
throw new IllegalStateException("Failed to initialize. Terminating");
}
// Set some implementations so that the static methods work properly
Timer.SetImplementation(new HardwareTimer());

View File

@@ -16,7 +16,7 @@ import java.nio.ByteBuffer;
public class HAL extends JNIWrapper {
public static native void waitForDSData();
public static native int initialize(int mode);
public static native boolean initialize(int timeout, int mode);
public static native void observeUserProgramStarting();