Eureka! Figured out why libedit is breaking in prewarm on macOS via launchd

The prewarm zygote imports the world. shell.py had a top level import
for readline. Which means readline was being imported pre-fork. And of
course as is traditional with Apple libedit is not fork safe. Probably
because it initializes its internal IO routines based on the stdio
handles at time of import which are the handles kitty gets from launchd
This commit is contained in:
Kovid Goyal 2022-08-30 19:35:17 +05:30
parent 78056c659c
commit fca0999814
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 4 additions and 14 deletions

View File

@ -476,15 +476,6 @@ def main(args: List[str]) -> Response:
loop.loop(phandler)
return {'items': items, 'response': phandler.response}
rd = getattr(sys, 'kitty_run_data')
if 'prewarmed' in rd and 'launched_by_launch_services' in rd:
# bloody libedit doesnt work in the prewarmed process run from launch
# services for reasons I really dont care enough to investigate
loop = Loop()
phandler = Password(cli_opts, prompt, is_password=False, initial_text=cli_opts.default or '')
loop.loop(phandler)
return {'items': items, 'response': phandler.response}
import readline as rl
readline = rl
from kitty.shell import init_readline

View File

@ -3,7 +3,6 @@
import os
import sys
from typing import Any, Callable, Dict, Generator, Optional, Sequence, Tuple
from kitty.fast_data_types import wcswidth
@ -149,9 +148,6 @@ class PathCompleter:
def get_path(prompt: str = '> ') -> str:
rd = getattr(sys, 'kitty_run_data')
if 'prewarmed' in rd and 'launched_by_launch_services' in rd:
return input(prompt)
return PathCompleter(prompt).input()

View File

@ -2,7 +2,6 @@
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os
import readline
import shlex
import sys
import traceback
@ -39,6 +38,7 @@ def match_commands() -> Tuple[str, ...]:
@run_once
def init_readline() -> None:
import readline
global is_libedit
with suppress(OSError):
readline.read_init_file()
@ -90,6 +90,7 @@ class Completer:
self.history_path = os.path.join(ddir, 'shell.history')
def complete(self, text: str, state: int) -> Optional[str]:
import readline
if state == 0:
line = readline.get_line_buffer()
cmdline = shlex.split(line)
@ -102,6 +103,7 @@ class Completer:
return None
def __enter__(self) -> 'Completer':
import readline
with suppress(Exception):
readline.read_history_file(self.history_path)
readline.set_completer(self.complete)
@ -110,6 +112,7 @@ class Completer:
return self
def __exit__(self, *a: Any) -> None:
import readline
readline.write_history_file(self.history_path)