IQ.Pilot Release Commit @ f2a861c

This commit is contained in:
IQ.Lvbs CI [bot]
2026-09-02 15:07:09 -05:00
parent b42569dbca
commit e8748fd704
5497 changed files with 316070 additions and 179848 deletions

View File

@@ -0,0 +1,104 @@
import errno
import fcntl
import os
import sys
import pathlib
import shutil
import signal
import subprocess
import tempfile
import threading
from iqpilot.common.basedir import BASEDIR
from iqpilot.common.params import Params
def unblock_stdout() -> None:
# get a non-blocking stdout
child_pid, child_pty = os.forkpty()
if child_pid != 0: # parent
# child is in its own process group, manually pass kill signals
signal.signal(signal.SIGINT, lambda signum, frame: os.kill(child_pid, signal.SIGINT))
signal.signal(signal.SIGTERM, lambda signum, frame: os.kill(child_pid, signal.SIGTERM))
fcntl.fcntl(sys.stdout, fcntl.F_SETFL, fcntl.fcntl(sys.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
while True:
try:
dat = os.read(child_pty, 4096)
except OSError as e:
if e.errno == errno.EIO:
break
continue
if not dat:
break
try:
sys.stdout.write(dat.decode('utf8'))
except (OSError, UnicodeDecodeError):
pass
# os.wait() returns a tuple with the pid and a 16 bit value
# whose low byte is the signal number and whose high byte is the exit status
exit_status = os.wait()[1] >> 8
os._exit(exit_status)
def write_onroad_params(started, params):
params.put_bool("IsOnroad", started)
params.put_bool("IsOffroad", not started)
def heal_param_perms():
"""Self-heal for a boot-bricking failure mode: a stray root process occasionally
writes a param (seen with RouteCount/CurrentRoute) as root:root 0600, which manager
(comma) then can't read — crashing save_bootlog and any param read. Detect params we
don't own and chown them back + make them readable. Needs root to chown another user's
file, so it shells to passwordless sudo (device grants it); best-effort, never raises,
never blocks boot. No-op when everything is already ours (the common case: no sudo)."""
try:
param_path = Params().get_param_path()
uid, gid = os.getuid(), os.getgid()
stray = []
for name in os.listdir(param_path):
p = os.path.join(param_path, name)
try:
if os.stat(p).st_uid != uid:
stray.append(p)
except OSError:
pass
if stray:
subprocess.run(["sudo", "-n", "chown", f"{uid}:{gid}", *stray], check=False, timeout=15,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.run(["sudo", "-n", "chmod", "644", *stray], check=False, timeout=15,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except Exception:
pass
def save_bootlog():
# copy current params
tmp = tempfile.mkdtemp()
params_dirname = pathlib.Path(Params().get_param_path()).name
params_dir = os.path.join(tmp, params_dirname)
# Params are rewritten atomically (unlink + rename) by other processes, so a
# value can vanish between copytree's listing and the copy; a param may also be
# unreadable (e.g. a root-owned RouteCount/CurrentRoute). Skip any file we can't
# copy instead of raising — the bootlog snapshot is best-effort and must NOT block boot.
def _copy_skip_missing(src, dst, *, follow_symlinks=True):
try:
shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
except OSError:
pass
shutil.copytree(Params().get_param_path(), params_dir, dirs_exist_ok=True, copy_function=_copy_skip_missing)
def fn(tmpdir):
env = os.environ.copy()
env['PARAMS_COPY_PATH'] = tmpdir
subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "iqpilot/system/loggerd"), env=env)
shutil.rmtree(tmpdir)
t = threading.Thread(target=fn, args=(tmp, ))
t.daemon = True
t.start()