From bb09fd0d4ed59e9cec2cc83268fc912461e54a87 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 21 Jan 2025 18:32:33 -0800 Subject: [PATCH] pandad: reset safety mode on exit (#32103) * boardd: reset safety mode on exit old-commit-hash: dd18ccbf0a9ab72ace0a7533632d5939c0719953 * comment old-commit-hash: 01b598e8dde93548f7783be19b1cb37d22fadc23 * log it old-commit-hash: 181c4d412e9e3a9c576934e16fc26a9b6e07a117 * logmessaged might not be alive old-commit-hash: 7483ba0eac42875a822df97596d23ff277bf3865 * reproduction, manager gets SIGTERM from python_process old-commit-hash: b90402bd776c3933bfe3dd60998f9913b4bd0068 * even smaller repro old-commit-hash: 03dd430b7131da2b48243714df0513c6a1e594f0 * should work old-commit-hash: 388c4273385ee4c67b1a229ccb9abac6dd94dd0f * let's not change that rn old-commit-hash: d057299058503e8fb792b5a765d0da4af6bef943 * something like this old-commit-hash: 123d6ed845d662aec2bd95d1ccf9c2782308d693 * pandad.cc should receive same SIGTERM and exit old-commit-hash: afc5ef6b916c54ac2ec471d144f601ead71250cb * stash old-commit-hash: e02e0dc488de51c5d40d227c4c2202ba40436d8d * remove debugging old-commit-hash: ac170d0ca32a4285be22e28ec7730fcba3d0697d * remove debugging old-commit-hash: 50949600aeed231347cc4c600a8a7d24accde674 * match behavior old-commit-hash: 5f24167c58caf98b641af2f63f839015e404c349 * convention old-commit-hash: 1664113a232c4b1a3aa67073e9e8cebef414518f * systemd option old-commit-hash: 95183ff77842fcb9592715db07396be28d778197 * manager option old-commit-hash: 2071893299cb32c3a7cd8a444d8d386c5fa96511 * just curious if this works, change to ELM327 on exit old-commit-hash: 9674ed525134aa03f995942b18163cb047a59c5b * Revert "just curious if this works, change to ELM327 on exit" This reverts commit d4ae294d419dc3d787d11dee4474799f3fb2acef. old-commit-hash: 6d24edd1635ddd0b8ed68a4a4fc8aaaa88984e45 * check onroad same update * useless * comment * fix * debug * Revert "debug" This reverts commit 2bb138610ea7b26d8610d36ef3f0bbb2d6ada388. * Update common/util.h * double wait does not work, blocking in signal handler not good, exit on do_exit, change to SIGINT, use existing stop to support ctrl+c nope * organize? * no sys * None --------- Co-authored-by: Shane Smiskol --- selfdrive/pandad/pandad.cc | 22 ++++++++++++++++------ selfdrive/pandad/pandad.py | 23 ++++++++++++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc index 8439616c33..e6ef4a4072 100644 --- a/selfdrive/pandad/pandad.cc +++ b/selfdrive/pandad/pandad.cc @@ -323,9 +323,7 @@ void send_peripheral_state(Panda *panda, PubMaster *pm) { pm->send("peripheralState", msg); } -void process_panda_state(std::vector &pandas, PubMaster *pm, bool spoofing_started) { - static SubMaster sm({"selfdriveState"}); - +void process_panda_state(std::vector &pandas, PubMaster *pm, bool engaged, bool spoofing_started) { std::vector connected_serials; for (Panda *p : pandas) { connected_serials.push_back(p->hw_serial()); @@ -361,8 +359,6 @@ void process_panda_state(std::vector &pandas, PubMaster *pm, bool spoof } } - sm.update(0); - const bool engaged = sm.allAliveAndValid({"selfdriveState"}) && sm["selfdriveState"].getSelfdriveState().getEnabled(); for (const auto &panda : pandas) { panda->send_heartbeat(engaged); } @@ -428,9 +424,11 @@ void pandad_run(std::vector &pandas) { std::thread send_thread(can_send_thread, pandas, fake_send); RateKeeper rk("pandad", 100); + SubMaster sm({"selfdriveState"}); PubMaster pm({"can", "pandaStates", "peripheralState"}); PandaSafety panda_safety(pandas); Panda *peripheral_panda = pandas[0]; + bool engaged = false; // Main loop: receive CAN data and process states while (!do_exit && check_all_connected(pandas)) { @@ -443,7 +441,9 @@ void pandad_run(std::vector &pandas) { // Process panda state at 10 Hz if (rk.frame() % 10 == 0) { - process_panda_state(pandas, &pm, spoofing_started); + sm.update(0); + engaged = sm.allAliveAndValid({"selfdriveState"}) && sm["selfdriveState"].getSelfdriveState().getEnabled(); + process_panda_state(pandas, &pm, engaged, spoofing_started); panda_safety.configureSafetyMode(); } @@ -455,6 +455,16 @@ void pandad_run(std::vector &pandas) { rk.keepTime(); } + // Close relay on exit to prevent a fault + const bool is_onroad = Params().getBool("IsOnroad"); + if (is_onroad && !engaged) { + for (auto &p : pandas) { + if (p->connected()) { + p->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); + } + } + } + send_thread.join(); } diff --git a/selfdrive/pandad/pandad.py b/selfdrive/pandad/pandad.py index 12accdbf5e..fd6668feba 100755 --- a/selfdrive/pandad/pandad.py +++ b/selfdrive/pandad/pandad.py @@ -3,8 +3,8 @@ import os import usb1 import time +import signal import subprocess -from typing import NoReturn from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH from openpilot.common.basedir import BASEDIR @@ -61,13 +61,25 @@ def flash_panda(panda_serial: str) -> Panda: return panda -def main() -> NoReturn: +def main() -> None: + # signal pandad to close the relay and exit + def signal_handler(signum, frame): + cloudlog.info(f"Caught signal {signum}, exiting") + nonlocal do_exit + do_exit = True + if process is not None: + process.send_signal(signal.SIGINT) + + process = None + do_exit = False + signal.signal(signal.SIGINT, signal_handler) + count = 0 first_run = True params = Params() no_internal_panda_count = 0 - while True: + while not do_exit: try: count += 1 cloudlog.event("pandad.flash_and_connect", count=count) @@ -159,8 +171,9 @@ def main() -> NoReturn: # run pandad with all connected serials as arguments os.environ['MANAGER_DAEMON'] = 'pandad' - os.chdir(os.path.join(BASEDIR, "selfdrive/pandad")) - subprocess.run(["./pandad", *panda_serials], check=True) + process = subprocess.Popen(["./pandad", *panda_serials], cwd=os.path.join(BASEDIR, "selfdrive/pandad")) + process.wait() + if __name__ == "__main__": main()