mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
80fbb4f6db
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Kacper Rączy <gfw.kra@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
134 lines
4.4 KiB
Python
134 lines
4.4 KiB
Python
"""Manager-supervised local Galaxy service across ignition changes."""
|
|
|
|
import os
|
|
import signal
|
|
import threading
|
|
import time
|
|
|
|
from openpilot.starpilot.galaxy.server import make_server
|
|
from openpilot.starpilot.galaxy.server import make_remote_server
|
|
from openpilot.starpilot.galaxy.remote import default_remote_pairing, make_gateway_auth_server
|
|
from openpilot.starpilot.galaxy.remote_service import supervise_tunnel
|
|
|
|
|
|
def serve_managed(server, *, extra_servers=(), tunnel=None) -> None:
|
|
# The manual server retains its normal threading policy. A managed child has
|
|
# a five-second stop grace, so a slow request cannot keep the process alive.
|
|
server.daemon_threads = True
|
|
server.block_on_close = False
|
|
stop = threading.Event()
|
|
errors: list[BaseException] = []
|
|
|
|
def request_stop(signum, frame):
|
|
stop.set()
|
|
|
|
def serve():
|
|
try:
|
|
server.serve_forever(poll_interval=0.1)
|
|
except BaseException as exc:
|
|
errors.append(exc)
|
|
stop.set()
|
|
|
|
def serve_extra(extra):
|
|
try:
|
|
extra.serve_forever(poll_interval=0.1)
|
|
if not stop.is_set():
|
|
errors.append(RuntimeError('Galaxy auxiliary listener stopped'))
|
|
stop.set()
|
|
except BaseException as exc:
|
|
errors.append(exc)
|
|
stop.set()
|
|
|
|
def serve_tunnel():
|
|
try:
|
|
assert tunnel is not None
|
|
tunnel(stop)
|
|
if not stop.is_set():
|
|
errors.append(RuntimeError('Galaxy tunnel supervisor stopped'))
|
|
stop.set()
|
|
except BaseException as exc:
|
|
errors.append(exc)
|
|
stop.set()
|
|
|
|
old_handlers = {sig: signal.getsignal(sig) for sig in (signal.SIGINT, signal.SIGTERM)}
|
|
for sig in old_handlers:
|
|
signal.signal(sig, request_stop)
|
|
|
|
worker = threading.Thread(target=serve, name='galaxy-http', daemon=True)
|
|
extras = [threading.Thread(target=serve_extra, args=(extra,), daemon=True)
|
|
for extra in extra_servers]
|
|
tunnel_worker = threading.Thread(target=serve_tunnel, daemon=True) if tunnel is not None else None
|
|
started = False
|
|
try:
|
|
for extra, thread in zip(extra_servers, extras, strict=True):
|
|
extra.daemon_threads = True
|
|
thread.start()
|
|
worker.start()
|
|
started = True
|
|
if tunnel_worker is not None:
|
|
tunnel_worker.start()
|
|
while worker.is_alive() and not stop.wait(0.1):
|
|
pass
|
|
finally:
|
|
stop.set()
|
|
drained = False
|
|
try:
|
|
if tunnel_worker is not None and tunnel_worker.is_alive():
|
|
tunnel_worker.join(timeout=6)
|
|
for extra, thread in zip(extra_servers, extras, strict=True):
|
|
if thread.is_alive():
|
|
extra.shutdown()
|
|
thread.join(timeout=0.5)
|
|
if started:
|
|
server.shutdown()
|
|
worker.join(timeout=0.5)
|
|
# Both web listeners use the same owners. One deadline bounds their
|
|
# accepted requests before any shared reader can be closed.
|
|
deadline = time.monotonic() + 4.0
|
|
drained = not started or server.drain_requests(max(0.0, deadline - time.monotonic()))
|
|
for extra in extra_servers:
|
|
drain = getattr(extra, 'drain_requests', None)
|
|
if callable(drain):
|
|
extra_drained = drain(max(0.0, deadline - time.monotonic()))
|
|
drained = drained and extra_drained
|
|
finally:
|
|
try:
|
|
for extra in extra_servers:
|
|
extra.server_close()
|
|
finally:
|
|
try:
|
|
server.server_close(close_sources=drained)
|
|
finally:
|
|
for sig, handler in old_handlers.items():
|
|
signal.signal(sig, handler)
|
|
|
|
if errors:
|
|
raise RuntimeError('Galaxy HTTP service stopped unexpectedly') from errors[0]
|
|
|
|
|
|
def main() -> None:
|
|
if os.getenv('STARPILOT_GALAXY_DISABLE') == '1':
|
|
raise RuntimeError('Managed Galaxy disabled by STARPILOT_GALAXY_DISABLE=1')
|
|
server = make_server(port=8082, host='0.0.0.0')
|
|
try:
|
|
server.start_drive_history()
|
|
pairing = default_remote_pairing()
|
|
remote_server = make_remote_server(server)
|
|
try:
|
|
from openpilot.common.params import Params
|
|
params = Params()
|
|
from openpilot.starpilot.connect.provider import galaxy_device_id
|
|
auth_server = make_gateway_auth_server(pairing, lambda: galaxy_device_id(params))
|
|
except BaseException:
|
|
remote_server.server_close()
|
|
raise
|
|
except BaseException:
|
|
server.server_close()
|
|
raise
|
|
print(f'Galaxy local/LAN service listening on port {server.server_port}', flush=True)
|
|
serve_managed(server, extra_servers=(remote_server, auth_server), tunnel=lambda stop: supervise_tunnel(stop, pairing))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|