Esempio n. 1
0
    def test_signal_handling(self):
        expecting_code = 0
        expecting_signal = 0
        expecting_value = 0
        found_signal = False

        def handle_signal(siginfo):
            nonlocal found_signal
            if expecting_signal:
                self.ae(siginfo.si_signo, expecting_signal)
            if expecting_code is not None:
                self.ae(siginfo.si_code, expecting_code)
            self.ae(siginfo.sival_int, expecting_value)
            if expecting_code in (CLD_EXITED, CLD_KILLED):
                p.wait(1)
                p.stdin.close()
            found_signal = True

        def assert_signal():
            nonlocal found_signal
            found_signal = False
            st = time.monotonic()
            while time.monotonic() - st < 5:
                for (fd, event) in poll.poll(10):
                    if fd == signal_read_fd:
                        read_signals(signal_read_fd, handle_signal)
                if found_signal:
                    break
            self.assertTrue(found_signal, f'Failed to to get SIGCHLD for signal {signal}')

        def t(signal, q, expecting_sig=signal.SIGCHLD):
            nonlocal expecting_code, found_signal, expecting_signal
            expecting_code = q
            expecting_signal = expecting_sig.value
            if signal is not None:
                p.send_signal(signal)
            assert_signal()

        poll = select.poll()
        p = subprocess.Popen([kitty_exe(), '+runpy', 'input()'], stderr=subprocess.DEVNULL, stdin=subprocess.PIPE)
        signal_read_fd = install_signal_handlers(signal.SIGCHLD, signal.SIGUSR1)[0]
        try:
            poll.register(signal_read_fd, select.POLLIN)
            t(signal.SIGINT, CLD_KILLED)
            p = subprocess.Popen([kitty_exe(), '+runpy', 'input()'], stderr=subprocess.DEVNULL, stdin=subprocess.PIPE)
            p.stdin.close()
            t(None, os.CLD_EXITED)
            expecting_code = None
            expecting_signal = signal.SIGUSR1.value
            os.kill(os.getpid(), signal.SIGUSR1)
            assert_signal()
            expecting_value = 17 if has_sigqueue else 0
            sigqueue(os.getpid(), signal.SIGUSR1.value, expecting_value)
            assert_signal()

        finally:
            remove_signal_handlers()
Esempio n. 2
0
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)
Esempio n. 3
0
    def test_prewarming(self):
        from kitty.prewarm import fork_prewarm_process

        cwd = tempfile.gettempdir()
        env = {'TEST_ENV_PASS': '******'}
        cols = 117
        stdin_data = 'from_stdin'
        pty = self.create_pty(cols=cols)
        ttyname = os.ttyname(pty.slave_fd)
        opts = get_options()
        opts.config_overrides = 'font_family prewarm',
        p = fork_prewarm_process(opts, use_exec=True)
        if p is None:
            return
        p.take_from_worker_fd(create_file=True)
        child = p(pty.slave_fd, [kitty_exe(), '+runpy', """\
import os, json; from kitty.utils import *; from kitty.fast_data_types import get_options; print(json.dumps({
        'cterm': os.ctermid(),
        'ttyname': os.ttyname(sys.stdout.fileno()),
        'cols': read_screen_size().cols,
        'cwd': os.getcwd(),
        'env': os.environ.get('TEST_ENV_PASS'),
        'pid': os.getpid(),
        'font_family': get_options().font_family,
        'stdin': sys.stdin.read(),

        'done': 'hello',
        }, indent=2))"""], cwd=cwd, env=env, stdin_data=stdin_data)
        self.assertFalse(pty.screen_contents().strip())
        p.mark_child_as_ready(child.child_id)
        pty.wait_till(lambda: 'hello' in pty.screen_contents())
        data = json.loads(pty.screen_contents())
        self.ae(data['cols'], cols)
        self.assertTrue(data['cterm'])
        self.ae(data['ttyname'], ttyname)
        self.ae(os.path.realpath(data['cwd']), os.path.realpath(cwd))
        self.ae(data['env'], env['TEST_ENV_PASS'])
        self.ae(data['font_family'], 'prewarm')
        self.ae(int(p.from_worker.readline()), data['pid'])
Esempio n. 4
0
    def test_prewarming(self):
        from kittens.prewarm.main import PrewarmProcess

        p = PrewarmProcess(create_file_to_read_from_worker=True)
        cwd = tempfile.gettempdir()
        env = {'TEST_ENV_PASS': '******'}
        cols = 117
        stdin_data = 'from_stdin'
        pty = self.create_pty(cols=cols)
        ttyname = os.ttyname(pty.slave_fd)
        child = p(pty.slave_fd, [
            kitty_exe(), '+runpy',
            """import os, json; from kitty.utils import *; print(json.dumps({
        'cterm': os.ctermid(),
        'ttyname': os.ttyname(sys.stdout.fileno()),
        'cols': read_screen_size().cols,
        'cwd': os.getcwd(),
        'env': os.environ.get('TEST_ENV_PASS'),
        'pid': os.getpid(),
        'stdin': sys.stdin.read(),

        'done': 'hello',
        }, indent=2))"""
        ],
                  cwd=cwd,
                  env=env,
                  stdin_data=stdin_data)
        self.assertFalse(pty.screen_contents().strip())
        p.mark_child_as_ready(child.child_id)
        pty.wait_till(lambda: 'hello' in pty.screen_contents())
        data = json.loads(pty.screen_contents())
        self.ae(data['cols'], cols)
        self.assertTrue(data['cterm'])
        self.ae(data['ttyname'], ttyname)
        self.ae(os.path.realpath(data['cwd']), os.path.realpath(cwd))
        self.ae(data['env'], env['TEST_ENV_PASS'])
        self.ae(int(p.from_worker.readline()), data['pid'])
Esempio n. 5
0
 def test_exe(self) -> None:
     from kitty.constants import kitty_exe
     exe = kitty_exe()
     self.assertTrue(os.access(exe, os.X_OK))
     self.assertTrue(os.path.isfile(exe))
     self.assertIn('kitty', os.path.basename(exe))
Esempio n. 6
0
 def cmd_to_run_python_code(self, code):
     from kitty.constants import kitty_exe
     return [kitty_exe(), '+runpy', code]