示例#1
0
def manager_thread():
    cloudlog.info("manager start")
    cloudlog.info({"environ": os.environ})

    # save boot log
    subprocess.call("./bootlog",
                    cwd=os.path.join(BASEDIR, "selfdrive/loggerd"))

    ignore = []
    if os.getenv("NOBOARD") is not None:
        ignore.append("pandad")
    if os.getenv("BLOCK") is not None:
        ignore += os.getenv("BLOCK").split(",")

    # start offroad
    if EON and "QT" not in os.environ:
        pm_apply_packages('enable')
        start_offroad()

    started_prev = False
    params = Params()
    sm = messaging.SubMaster(['deviceState'])
    pm = messaging.PubMaster(['managerState'])

    while True:
        sm.update()
        not_run = ignore[:]

        if sm['deviceState'].freeSpacePercent < 5:
            not_run.append("loggerd")

        started = sm['deviceState'].started
        driverview = params.get("IsDriverViewEnabled") == b"1"
        ensure_running(managed_processes.values(), started, driverview,
                       not_run)

        # trigger an update after going offroad
        if started_prev and not started and 'updated' in managed_processes:
            os.sync()
            managed_processes['updated'].signal(signal.SIGHUP)

        started_prev = started

        running_list = [
            "%s%s\u001b[0m" %
            ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
            for p in managed_processes.values() if p.proc
        ]
        cloudlog.debug(' '.join(running_list))

        # send managerState
        msg = messaging.new_message('managerState')
        msg.managerState.processes = [
            p.get_process_state_msg() for p in managed_processes.values()
        ]
        pm.send('managerState', msg)

        # Exit main loop when uninstall is needed
        if params.get("DoUninstall", encoding='utf8') == "1":
            break
示例#2
0
def manager_thread() -> None:
    cloudlog.bind(daemon="manager")
    cloudlog.info("manager start")
    cloudlog.info({"environ": os.environ})

    params = Params()

    ignore: List[str] = []
    if params.get("DongleId",
                  encoding='utf8') in (None, UNREGISTERED_DONGLE_ID):
        ignore += ["manage_athenad", "uploader"]
    if os.getenv("NOBOARD") is not None:
        ignore.append("pandad")
    ignore += [x for x in os.getenv("BLOCK", "").split(",") if len(x) > 0]

    sm = messaging.SubMaster(['deviceState', 'carParams'],
                             poll=['deviceState'])
    pm = messaging.PubMaster(['managerState'])

    ensure_running(managed_processes.values(),
                   False,
                   params=params,
                   CP=sm['carParams'],
                   not_run=ignore)

    while True:
        sm.update()

        started = sm['deviceState'].started
        ensure_running(managed_processes.values(),
                       started,
                       params=params,
                       CP=sm['carParams'],
                       not_run=ignore)

        running = ' '.join(
            "%s%s\u001b[0m" %
            ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
            for p in managed_processes.values() if p.proc)
        print(running)
        cloudlog.debug(running)

        # send managerState
        msg = messaging.new_message('managerState')
        msg.managerState.processes = [
            p.get_process_state_msg() for p in managed_processes.values()
        ]
        pm.send('managerState', msg)

        # Exit main loop when uninstall/shutdown/reboot is needed
        shutdown = False
        for param in ("DoUninstall", "DoShutdown", "DoReboot"):
            if params.get_bool(param):
                shutdown = True
                params.put("LastManagerExitReason", param)
                cloudlog.warning(f"Shutting down manager - {param} set")

        if shutdown:
            break
示例#3
0
def manager_thread():
  cloudlog.info("manager start")
  cloudlog.info({"environ": os.environ})

  params = Params()

  ignore = []
  if params.get("DongleId", encoding='utf8') == UNREGISTERED_DONGLE_ID:
    ignore += ["manage_athenad", "uploader"]
  if os.getenv("NOBOARD") is not None:
    ignore.append("pandad")
  if os.getenv("BLOCK") is not None:
    ignore += os.getenv("BLOCK").split(",")

  ensure_running(managed_processes.values(), started=False, not_run=ignore)

  started_prev = False
  sm = messaging.SubMaster(['deviceState'])
  pm = messaging.PubMaster(['managerState'])

  while True:
    sm.update()
    not_run = ignore[:]

    if sm['deviceState'].freeSpacePercent < 5:
      not_run.append("loggerd")

    started = sm['deviceState'].started
    driverview = params.get_bool("IsDriverViewEnabled")
    ensure_running(managed_processes.values(), started, driverview, not_run)

    # trigger an update after going offroad
    if started_prev and not started and 'updated' in managed_processes:
      os.sync()
      managed_processes['updated'].signal(signal.SIGHUP)

    started_prev = started

    running = ' '.join(["%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
                       for p in managed_processes.values() if p.proc])
    print(running)
    cloudlog.debug(running)

    # send managerState
    msg = messaging.new_message('managerState')
    msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()]
    pm.send('managerState', msg)

    # Exit main loop when uninstall/shutdown/reboot is needed
    shutdown = False
    for param in ("DoUninstall", "DoShutdown", "DoReboot"):
      if params.get_bool(param):
        cloudlog.warning(f"Shutting down manager - {param} set")
        shutdown = True

    if shutdown:
      break
示例#4
0
def manager_thread():

  Process(name="shutdownd", target=launcher, args=("selfdrive.shutdownd",)).start()
  system("am startservice com.neokii.optool/.MainService")
  system("am startservice com.neokii.openpilot/.MainService")

  cloudlog.info("manager start")
  cloudlog.info({"environ": os.environ})

  # save boot log
  #subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd"))

  params = Params()

  ignore = []
  if os.getenv("NOBOARD") is not None:
    ignore.append("pandad")
  if os.getenv("BLOCK") is not None:
    ignore += os.getenv("BLOCK").split(",")

  ensure_running(managed_processes.values(), started=False, not_run=ignore)

  started_prev = False
  sm = messaging.SubMaster(['deviceState'])
  pm = messaging.PubMaster(['managerState'])

  while True:
    sm.update()
    not_run = ignore[:]

    if sm['deviceState'].freeSpacePercent < 5:
      not_run.append("loggerd")

    started = sm['deviceState'].started
    driverview = params.get_bool("IsDriverViewEnabled")
    ensure_running(managed_processes.values(), started, driverview, not_run)

    # trigger an update after going offroad
    if started_prev and not started and 'updated' in managed_processes:
      os.sync()
      managed_processes['updated'].signal(signal.SIGHUP)

    started_prev = started

    running_list = ["%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
                    for p in managed_processes.values() if p.proc]
    cloudlog.debug(' '.join(running_list))

    # send managerState
    msg = messaging.new_message('managerState')
    msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()]
    pm.send('managerState', msg)

    # TODO: let UI handle this
    # Exit main loop when uninstall is needed
    if params.get_bool("DoUninstall"):
      break
示例#5
0
def manager_cleanup():
  # send signals to kill all procs
  for p in managed_processes.values():
    p.stop(block=False)

  # ensure all are killed
  for p in managed_processes.values():
    p.stop(block=True)

  cloudlog.info("everything is dead")
示例#6
0
def manager_cleanup():
    if EON:
        pm_apply_packages('disable')

    for p in managed_processes.values():
        p.stop()

    cloudlog.info("everything is dead")
示例#7
0
def manager_cleanup():
    if EON and Params().get_bool("OpkrApksEnable"):
        pm_apply_packages('disable')

    for p in managed_processes.values():
        p.stop()

    cloudlog.info("everything is dead")
示例#8
0
def manager_prepare(spinner=None):
    # build all processes
    os.chdir(os.path.dirname(os.path.abspath(__file__)))

    total = 100.0 - (0 if PREBUILT else MAX_BUILD_PROGRESS)
    for i, p in enumerate(managed_processes.values()):
        p.prepare()
        if spinner:
            perc = (100.0 - total) + total * (i + 1) / len(managed_processes)
            spinner.update_progress(perc, 100.)
示例#9
0
import os
import signal
import time
import unittest

import selfdrive.manager.manager as manager
from selfdrive.hardware import EON
from selfdrive.manager.process import DaemonProcess
from selfdrive.manager.process_config import managed_processes

os.environ['FAKEUPLOAD'] = "1"

# TODO: make eon fast
MAX_STARTUP_TIME = 30 if EON else 15
ALL_PROCESSES = [
    p.name for p in managed_processes.values()
    if (type(p) is not DaemonProcess) and (p.name not in ['updated', 'pandad'])
]


class TestManager(unittest.TestCase):
    def setUp(self):
        os.environ['PASSIVE'] = '0'

    def tearDown(self):
        manager.manager_cleanup()

    def test_manager_prepare(self):
        os.environ['PREPAREONLY'] = '1'
        manager.main()
示例#10
0
def regen_segment(lr, frs=None, outdir=FAKEDATA):
    lr = list(lr)
    if frs is None:
        frs = dict()

    # setup env
    params = Params()
    params.clear_all()
    params.put_bool("Passive", False)
    params.put_bool("OpenpilotEnabledToggle", True)

    os.environ["LOG_ROOT"] = outdir
    os.environ["REPLAY"] = "1"

    os.environ['SKIP_FW_QUERY'] = ""
    os.environ['FINGERPRINT'] = ""

    # TODO: remove after getting new route for mazda
    migration = {
        "Mazda CX-9 2021": "MAZDA CX-9 2021",
    }

    for msg in lr:
        if msg.which() == 'carParams':
            car_fingerprint = migration.get(msg.carParams.carFingerprint,
                                            msg.carParams.carFingerprint)
            if len(msg.carParams.carFw) and (car_fingerprint in FW_VERSIONS):
                params.put("CarParamsCache",
                           msg.carParams.as_builder().to_bytes())
            else:
                os.environ['SKIP_FW_QUERY'] = "1"
                os.environ['FINGERPRINT'] = car_fingerprint
        elif msg.which() == 'liveCalibration':
            params.put("CalibrationParams", msg.as_builder().to_bytes())

    vs, cam_procs = replay_cameras(lr, frs)

    fake_daemons = {
        'sensord': [
            multiprocessing.Process(target=replay_sensor_events,
                                    args=('sensorEvents', lr)),
        ],
        'pandad': [
            multiprocessing.Process(target=replay_service, args=('can', lr)),
            multiprocessing.Process(target=replay_service,
                                    args=('ubloxRaw', lr)),
            multiprocessing.Process(target=replay_panda_states,
                                    args=('pandaStates', lr)),
        ],
        'managerState': [
            multiprocessing.Process(target=replay_manager_state,
                                    args=('managerState', lr)),
        ],
        'thermald': [
            multiprocessing.Process(target=replay_device_state,
                                    args=('deviceState', lr)),
        ],
        'camerad': [
            *cam_procs,
        ],
    }

    try:
        # start procs up
        ignore = list(
            fake_daemons.keys()) + ['ui', 'manage_athenad', 'uploader']
        ensure_running(managed_processes.values(),
                       started=True,
                       not_run=ignore)
        for procs in fake_daemons.values():
            for p in procs:
                p.start()

        for _ in tqdm(range(60)):
            # ensure all procs are running
            for d, procs in fake_daemons.items():
                for p in procs:
                    if not p.is_alive():
                        raise Exception(f"{d}'s {p.name} died")
            time.sleep(1)
    finally:
        # kill everything
        for p in managed_processes.values():
            p.stop()
        for procs in fake_daemons.values():
            for p in procs:
                p.terminate()

    del vs

    r = params.get("CurrentRoute", encoding='utf-8')
    return os.path.join(outdir, r + "--0")
示例#11
0
def regen_segment(lr, frs=None, outdir=FAKEDATA):
  lr = list(lr)
  if frs is None:
    frs = dict()

  setup_env()
  params = Params()

  os.environ["LOG_ROOT"] = outdir
  os.environ['SKIP_FW_QUERY'] = ""
  os.environ['FINGERPRINT'] = ""

  # TODO: remove after getting new route for mazda
  migration = {
    "Mazda CX-9 2021": "MAZDA CX-9 2021",
  }

  for msg in lr:
    if msg.which() == 'carParams':
      car_fingerprint = migration.get(msg.carParams.carFingerprint, msg.carParams.carFingerprint)
      if len(msg.carParams.carFw) and (car_fingerprint in FW_VERSIONS):
        params.put("CarParamsCache", msg.carParams.as_builder().to_bytes())
      else:
        os.environ['SKIP_FW_QUERY'] = "1"
        os.environ['FINGERPRINT'] = car_fingerprint
    elif msg.which() == 'liveCalibration':
      params.put("CalibrationParams", msg.as_builder().to_bytes())

  vs, cam_procs = replay_cameras(lr, frs)

  fake_daemons = {
    'sensord': [
      multiprocessing.Process(target=replay_sensor_events, args=('sensorEvents', lr)),
    ],
    'pandad': [
      multiprocessing.Process(target=replay_service, args=('can', lr)),
      multiprocessing.Process(target=replay_service, args=('ubloxRaw', lr)),
      multiprocessing.Process(target=replay_panda_states, args=('pandaStates', lr)),
    ],
    'managerState': [
     multiprocessing.Process(target=replay_manager_state, args=('managerState', lr)),
    ],
    'thermald': [
      multiprocessing.Process(target=replay_device_state, args=('deviceState', lr)),
    ],
    'camerad': [
      *cam_procs,
    ],
  }

  try:
    # TODO: make first run of onnxruntime CUDA provider fast
    managed_processes["modeld"].start()
    managed_processes["dmonitoringmodeld"].start()
    time.sleep(5)

    # start procs up
    ignore = list(fake_daemons.keys()) + ['ui', 'manage_athenad', 'uploader']
    ensure_running(managed_processes.values(), started=True, params=Params(), CP=car.CarParams(), not_run=ignore)
    for procs in fake_daemons.values():
      for p in procs:
        p.start()

    for _ in tqdm(range(60)):
      # ensure all procs are running
      for d, procs in fake_daemons.items():
        for p in procs:
          if not p.is_alive():
            raise Exception(f"{d}'s {p.name} died")
      time.sleep(1)
  finally:
    # kill everything
    for p in managed_processes.values():
      p.stop()
    for procs in fake_daemons.values():
      for p in procs:
        p.terminate()

  del vs

  segment = params.get("CurrentRoute", encoding='utf-8') + "--0"
  seg_path = os.path.join(outdir, segment)
  # check to make sure openpilot is engaged in the route
  if not check_enabled(LogReader(os.path.join(seg_path, "rlog"))):
    raise Exception(f"Route never enabled: {segment}")

  return seg_path
示例#12
0
def manager_thread():
    cloudlog.info("manager start")
    cloudlog.info({"environ": os.environ})

    params = Params()

    dp_reg = params.get_bool('dp_reg')
    dp_logger = params.get_bool('dp_logger')
    dp_athenad = params.get_bool('dp_athenad')
    dp_uploader = params.get_bool('dp_uploader')
    dp_atl = params.get_bool('dp_atl')
    dp_jetson = params.get_bool('dp_jetson')
    dp_otisserv = params.get_bool('dp_otisserv')
    dp_mapd = params.get_bool('dp_mapd')
    if not dp_reg:
        dp_athenad = False
        dp_uploader = False
    # save boot log
    if dp_logger:
        subprocess.call("./bootlog",
                        cwd=os.path.join(BASEDIR, "selfdrive/loggerd"))

    ignore = []
    if dp_jetson:
        ignore += ['dmonitoringmodeld', 'dmonitoringd']
    if not params.get_bool('dp_dashcamd'):
        ignore += ['dashcamd']
    if not params.get_bool('dp_updated'):
        ignore += ['updated']
    if not dp_logger:
        ignore += [
            'logcatd', 'loggerd', 'proclogd', 'logmessaged', 'tombstoned'
        ]
    if not dp_athenad:
        ignore += ['manage_athenad']
    if not dp_athenad and not dp_uploader:
        ignore += ['deleter']
    if not dp_mapd:
        ignore += ['mapd']
    if not dp_otisserv:
        ignore += ['otisserv']
    if not dp_mapd and not dp_otisserv and not params.get_bool('dp_gpxd'):
        ignore += ['gpxd']
    if params.get("DongleId", encoding='utf8') == UNREGISTERED_DONGLE_ID:
        ignore += ["manage_athenad", "uploader"]
    if os.getenv("NOBOARD") is not None:
        ignore.append("pandad")
    if os.getenv("BLOCK") is not None:
        ignore += os.getenv("BLOCK").split(",")

    ensure_running(managed_processes.values(), started=False, not_run=ignore)

    started_prev = False
    sm = messaging.SubMaster(['deviceState'])
    pm = messaging.PubMaster(['managerState'])

    while True:
        sm.update()
        not_run = ignore[:]

        if sm['deviceState'].freeSpacePercent < 5:
            not_run.append("loggerd")

        started = sm['deviceState'].started
        driverview = params.get_bool("IsDriverViewEnabled")
        ensure_running(managed_processes.values(), started, driverview,
                       not_run)

        # trigger an update after going offroad
        if started_prev and not started and 'updated' in managed_processes:
            os.sync()
            managed_processes['updated'].signal(signal.SIGHUP)

        started_prev = started

        running_list = [
            "%s%s\u001b[0m" %
            ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
            for p in managed_processes.values() if p.proc
        ]
        cloudlog.debug(' '.join(running_list))

        # send managerState
        msg = messaging.new_message('managerState')
        msg.managerState.processes = [
            p.get_process_state_msg() for p in managed_processes.values()
        ]
        pm.send('managerState', msg)

        # TODO: let UI handle this
        # Exit main loop when uninstall is needed
        if params.get_bool("DoUninstall"):
            break
示例#13
0
def manager_thread(spinner=None):
    shutdownd = Process(name="shutdownd",
                        target=launcher,
                        args=("selfdrive.shutdownd", ))
    shutdownd.start()

    if EON:
        pm_grant("com.neokii.openpilot",
                 "android.permission.ACCESS_FINE_LOCATION")
        appops_set("com.neokii.optool", "SU", "allow")
        system("am startservice com.neokii.optool/.MainService")
        system("am startservice com.neokii.openpilot/.MainService")

    cloudlog.info("manager start")
    cloudlog.info({"environ": os.environ})

    # save boot log
    #subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd"))

    ignore = []
    if os.getenv("NOBOARD") is not None:
        ignore.append("pandad")
    if os.getenv("BLOCK") is not None:
        ignore += os.getenv("BLOCK").split(",")

    # start offroad
    if EON and "QT" not in os.environ:
        pm_apply_packages('enable')
        start_offroad()

    ensure_running(managed_processes.values(), started=False, not_run=ignore)
    if spinner:  # close spinner when ui has started
        spinner.close()

    started_prev = False
    params = Params()
    sm = messaging.SubMaster(['deviceState'])
    pm = messaging.PubMaster(['managerState'])

    while True:
        sm.update()
        not_run = ignore[:]

        if sm['deviceState'].freeSpacePercent < 5:
            not_run.append("loggerd")

        started = sm['deviceState'].started
        driverview = params.get("IsDriverViewEnabled") == b"1"
        ensure_running(managed_processes.values(), started, driverview,
                       not_run)

        # trigger an update after going offroad
        if started_prev and not started and 'updated' in managed_processes:
            os.sync()
            managed_processes['updated'].signal(signal.SIGHUP)

        started_prev = started

        running_list = [
            "%s%s\u001b[0m" %
            ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
            for p in managed_processes.values() if p.proc
        ]
        cloudlog.debug(' '.join(running_list))

        # send managerState
        msg = messaging.new_message('managerState')
        msg.managerState.processes = [
            p.get_process_state_msg() for p in managed_processes.values()
        ]
        pm.send('managerState', msg)

        # Exit main loop when uninstall is needed
        if params.get("DoUninstall", encoding='utf8') == "1":
            break
示例#14
0
def manager_thread() -> None:

    if EON:
        Process(name="autoshutdownd",
                target=launcher,
                args=("selfdrive.autoshutdownd", "autoshutdownd")).start()
        system("am startservice com.neokii.optool/.MainService")

    Process(name="road_speed_limiter",
            target=launcher,
            args=("selfdrive.road_speed_limiter",
                  "road_speed_limiter")).start()
    cloudlog.bind(daemon="manager")
    cloudlog.info("manager start")
    cloudlog.info({"environ": os.environ})

    params = Params()

    ignore: List[str] = []
    if params.get("DongleId",
                  encoding='utf8') in (None, UNREGISTERED_DONGLE_ID):
        ignore += ["manage_athenad", "uploader"]
    if os.getenv("NOBOARD") is not None:
        ignore.append("pandad")
    ignore += [x for x in os.getenv("BLOCK", "").split(",") if len(x) > 0]

    ensure_running(managed_processes.values(), started=False, not_run=ignore)

    started_prev = False
    sm = messaging.SubMaster(['deviceState'])
    pm = messaging.PubMaster(['managerState'])

    while True:
        sm.update()
        not_run = ignore[:]

        started = sm['deviceState'].started
        driverview = params.get_bool("IsDriverViewEnabled")
        ensure_running(managed_processes.values(), started, driverview,
                       not_run)

        # trigger an update after going offroad
        if started_prev and not started and 'updated' in managed_processes:
            os.sync()
            managed_processes['updated'].signal(signal.SIGHUP)

        started_prev = started

        running = ' '.join(
            "%s%s\u001b[0m" %
            ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
            for p in managed_processes.values() if p.proc)
        print(running)
        cloudlog.debug(running)

        # send managerState
        msg = messaging.new_message('managerState')
        msg.managerState.processes = [
            p.get_process_state_msg() for p in managed_processes.values()
        ]
        pm.send('managerState', msg)

        # Exit main loop when uninstall/shutdown/reboot is needed
        shutdown = False
        for param in ("DoUninstall", "DoShutdown", "DoReboot"):
            if params.get_bool(param):
                shutdown = True
                params.put("LastManagerExitReason", param)
                cloudlog.warning(f"Shutting down manager - {param} set")

        if shutdown:
            break
示例#15
0
#!/usr/bin/env python3
import os
import signal
import time
import unittest

import selfdrive.manager.manager as manager
from selfdrive.hardware import EON
from selfdrive.manager.process import DaemonProcess
from selfdrive.manager.process_config import managed_processes

os.environ['FAKEUPLOAD'] = "1"

# TODO: make eon fast
MAX_STARTUP_TIME = 30 if EON else 15
ALL_PROCESSES = [p.name for p in managed_processes.values() if (type(p) is not DaemonProcess) and p.enabled and (p.name not in ['updated', 'pandad'])]


class TestManager(unittest.TestCase):
  def setUp(self):
    os.environ['PASSIVE'] = '0'

  def tearDown(self):
    manager.manager_cleanup()

  def test_manager_prepare(self):
    os.environ['PREPAREONLY'] = '1'
    manager.main()

  def test_startup_time(self):
    for _ in range(10):
示例#16
0
def regen_segment(lr, frs=None, outdir=FAKEDATA, disable_tqdm=False):
    lr = migrate_carparams(list(lr))
    if frs is None:
        frs = dict()

    params = Params()
    os.environ["LOG_ROOT"] = outdir

    # Get and setup initial state
    CP = [m for m in lr if m.which() == 'carParams'][0].carParams
    controlsState = [m for m in lr
                     if m.which() == 'controlsState'][0].controlsState
    liveCalibration = [m for m in lr if m.which() == 'liveCalibration'][0]

    setup_env(CP=CP, controlsState=controlsState)
    params.put("CalibrationParams", liveCalibration.as_builder().to_bytes())

    vs, cam_procs = replay_cameras(lr, frs, disable_tqdm=disable_tqdm)
    fake_daemons = {
        'sensord': [
            multiprocessing.Process(target=replay_sensor_events,
                                    args=('sensorEvents', lr)),
        ],
        'pandad': [
            multiprocessing.Process(target=replay_service, args=('can', lr)),
            multiprocessing.Process(target=replay_service,
                                    args=('ubloxRaw', lr)),
            multiprocessing.Process(target=replay_panda_states,
                                    args=('pandaStates', lr)),
        ],
        'managerState': [
            multiprocessing.Process(target=replay_manager_state,
                                    args=('managerState', lr)),
        ],
        'thermald': [
            multiprocessing.Process(target=replay_device_state,
                                    args=('deviceState', lr)),
        ],
        'camerad': [
            *cam_procs,
        ],
    }

    try:
        # TODO: make first run of onnxruntime CUDA provider fast
        managed_processes["modeld"].start()
        managed_processes["dmonitoringmodeld"].start()
        time.sleep(5)

        # start procs up
        ignore = list(fake_daemons.keys()) + [
            'ui', 'manage_athenad', 'uploader', 'soundd'
        ]
        ensure_running(managed_processes.values(),
                       started=True,
                       params=Params(),
                       CP=car.CarParams(),
                       not_run=ignore)
        for procs in fake_daemons.values():
            for p in procs:
                p.start()

        for _ in tqdm(range(60), disable=disable_tqdm):
            # ensure all procs are running
            for d, procs in fake_daemons.items():
                for p in procs:
                    if not p.is_alive():
                        raise Exception(f"{d}'s {p.name} died")
            time.sleep(1)
    finally:
        # kill everything
        for p in managed_processes.values():
            p.stop()
        for procs in fake_daemons.values():
            for p in procs:
                p.terminate()

    del vs

    segment = params.get("CurrentRoute", encoding='utf-8') + "--0"
    seg_path = os.path.join(outdir, segment)
    # check to make sure openpilot is engaged in the route
    if not check_enabled(LogReader(os.path.join(seg_path, "rlog"))):
        raise Exception(f"Route did not engage for long enough: {segment}")

    return seg_path