|  |  |  | import errno
 | 
					
						
							|  |  |  | import fcntl
 | 
					
						
							|  |  |  | import os
 | 
					
						
							|  |  |  | import sys
 | 
					
						
							|  |  |  | import pathlib
 | 
					
						
							|  |  |  | import shutil
 | 
					
						
							|  |  |  | import signal
 | 
					
						
							|  |  |  | import subprocess
 | 
					
						
							|  |  |  | import tempfile
 | 
					
						
							|  |  |  | import threading
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from openpilot.common.basedir import BASEDIR
 | 
					
						
							|  |  |  | from openpilot.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 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)
 | 
					
						
							|  |  |  |   shutil.copytree(Params().get_param_path(), params_dir, dirs_exist_ok=True)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def fn(tmpdir):
 | 
					
						
							|  |  |  |     env = os.environ.copy()
 | 
					
						
							|  |  |  |     env['PARAMS_COPY_PATH'] = tmpdir
 | 
					
						
							|  |  |  |     subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "system/loggerd"), env=env)
 | 
					
						
							|  |  |  |     shutil.rmtree(tmpdir)
 | 
					
						
							|  |  |  |   t = threading.Thread(target=fn, args=(tmp, ))
 | 
					
						
							|  |  |  |   t.daemon = True
 | 
					
						
							|  |  |  |   t.start()
 |