Manage fd lifecycles a bit better

This commit is contained in:
Kovid Goyal 2022-06-08 13:26:27 +05:30
parent 116128ebb5
commit 0ed7b2f3c0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 15 additions and 14 deletions

View File

@ -143,14 +143,6 @@ def environ_of_process(pid: int) -> Dict[str, str]:
return parse_environ_block(_environ_of_process(pid))
def remove_cloexec(fd: int) -> None:
os.set_inheritable(fd, True)
def remove_blocking(fd: int) -> None:
os.set_blocking(fd, False)
def process_env() -> Dict[str, str]:
ans = dict(os.environ)
ssl_env_var = getattr(sys, 'kitty_ssl_env_var', None)
@ -178,7 +170,8 @@ def set_default_env(val: Optional[Dict[str, str]] = None) -> None:
def openpty() -> Tuple[int, int]:
master, slave = os.openpty() # Note that master and slave are in blocking mode
remove_cloexec(slave)
os.set_inheritable(slave, True)
os.set_inheritable(master, False)
fast_data_types.set_iutf8_fd(master, True)
return master, slave
@ -278,10 +271,12 @@ class Child:
self.is_prewarmed = is_prewarmable(self.argv)
if not self.is_prewarmed:
ready_read_fd, ready_write_fd = os.pipe()
remove_cloexec(ready_read_fd)
os.set_inheritable(ready_write_fd, False)
os.set_inheritable(ready_read_fd, True)
if stdin is not None:
stdin_read_fd, stdin_write_fd = os.pipe()
remove_cloexec(stdin_read_fd)
os.set_inheritable(stdin_write_fd, False)
os.set_inheritable(stdin_read_fd, True)
else:
stdin_read_fd = stdin_write_fd = -1
env = tuple(f'{k}={v}' for k, v in self.final_env().items())
@ -323,9 +318,15 @@ class Child:
os.close(ready_read_fd)
self.terminal_ready_fd = ready_write_fd
if self.child_fd is not None:
remove_blocking(self.child_fd)
os.set_blocking(self.child_fd, False)
return pid
def __del__(self) -> None:
fd = getattr(self, 'terminal_ready_fd', -1)
if fd > -1:
os.close(fd)
self.terminal_ready_fd = -1
def mark_terminal_ready(self) -> None:
if self.is_prewarmed:
fast_data_types.get_boss().prewarm.mark_child_as_ready(self.prewarmed_child.child_id)

View File

@ -821,13 +821,13 @@ def which(name: str, only_system: bool = False) -> Optional[str]:
def read_shell_environment(opts: Optional[Options] = None) -> Dict[str, str]:
ans: Optional[Dict[str, str]] = getattr(read_shell_environment, 'ans', None)
if ans is None:
from .child import openpty, remove_blocking
from .child import openpty
ans = {}
setattr(read_shell_environment, 'ans', ans)
import subprocess
shell = resolved_shell(opts)
master, slave = openpty()
remove_blocking(master)
os.set_blocking(master, False)
if '-l' not in shell and '--login' not in shell:
shell += ['-l']
if '-i' not in shell and '--interactive' not in shell: