def fork_prewarm_process(opts: Options, use_exec: bool = False) -> Optional[PrewarmProcess]: stdin_read, stdin_write = safe_pipe() stdout_read, stdout_write = safe_pipe() death_notify_read, death_notify_write = safe_pipe() if use_exec: import subprocess tp = subprocess.Popen([ kitty_exe(), '+runpy', f'from kitty.prewarm import exec_main; exec_main({stdin_read}, {stdout_write}, {death_notify_write})' ], pass_fds=(stdin_read, stdout_write, death_notify_write)) child_pid = tp.pid tp.returncode = 0 # prevent a warning when the popen object is deleted with the process still running else: child_pid = os.fork() if child_pid: # master os.close(stdin_read) os.close(stdout_write) os.close(death_notify_write) p = PrewarmProcess(child_pid, stdin_write, stdout_read, death_notify_read) if use_exec: p.reload_kitty_config() return p # child os.close(stdin_write) os.close(stdout_read) os.close(death_notify_read) set_options(opts) exec_main(stdin_read, stdout_write, death_notify_write) raise SystemExit(0)
def fork(shm_address: str, all_non_child_fds: Iterable[int]) -> Tuple[int, int]: sz = pos = 0 with SharedMemory(name=shm_address, unlink_on_exit=True) as shm: data = shm.read_data_with_size() cmd = json.loads(data) sz = cmd.get('stdin_size', 0) if sz: pos = shm.tell() shm.unlink_on_exit = False r, w = safe_pipe() ready_fd_read, ready_fd_write = safe_pipe() try: child_pid = os.fork() except OSError: if sz: with SharedMemory(shm_address, unlink_on_exit=True): pass if child_pid: # master process os.close(w) os.close(ready_fd_read) poll = select.poll() poll.register(r, select.POLLIN) tuple(poll.poll()) os.close(r) return child_pid, ready_fd_write # child process remove_signal_handlers() os.close(r) os.close(ready_fd_write) for fd in all_non_child_fds: os.close(fd) os.setsid() tty_name = cmd.get('tty_name') if tty_name: from kitty.fast_data_types import establish_controlling_tty sys.__stdout__.flush() sys.__stderr__.flush() establish_controlling_tty(tty_name, sys.__stdin__.fileno(), sys.__stdout__.fileno(), sys.__stderr__.fileno()) os.close(w) if shm.unlink_on_exit: child_main(cmd, ready_fd_read) else: with SharedMemory(shm_address, unlink_on_exit=True) as shm: stdin_data = memoryview(shm.mmap)[pos:pos + sz] if stdin_data: sys.stdin = MemoryViewReadWrapper(stdin_data) try: child_main(cmd, ready_fd_read) finally: stdin_data.release() sys.stdin = sys.__stdin__
def __init__( self, sanitize_bracketed_paste='[\x03\x04\x0e\x0f\r\x07\x7f\x8d\x8e\x8f\x90\x9b\x9d\x9e\x9f]' ): self.wakeup_read_fd, self.wakeup_write_fd = safe_pipe() # For some reason on macOS the DefaultSelector fails when tty_fd is # open('/dev/tty') self.sel = s = selectors.PollSelector() s.register(self.wakeup_read_fd, selectors.EVENT_READ) self.return_code = 0 self.read_allowed = True self.read_buf = '' self.decoder = codecs.getincrementaldecoder('utf-8')('ignore') try: self.iov_limit = max(os.sysconf('SC_IOV_MAX') - 1, 255) except Exception: self.iov_limit = 255 self.parse_input_from_terminal = partial(parse_input_from_terminal, self._on_text, self._on_dcs, self._on_csi, self._on_osc, self._on_pm, self._on_apc) self.ebs_pat = re.compile('([\177\r\x03\x04])') self.in_bracketed_paste = False self.sanitize_bracketed_paste = bool(sanitize_bracketed_paste) if self.sanitize_bracketed_paste: self.sanitize_ibp_pat = re.compile(sanitize_bracketed_paste) self.jobs_queue = Queue()