mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-22 20:17:45 +03:00
Use a pipe rather than a signal to wait for terminal ready
Simpler code, more robust since there is no longer a race between the installation of the signal handler and the dispatch of the signal
This commit is contained in:
parent
094ddd9333
commit
eb2ec1833c
@ -47,35 +47,22 @@ write_to_stderr(const char *text) {
|
||||
|
||||
#define exit_on_err(m) { write_to_stderr(m); write_to_stderr(": "); write_to_stderr(strerror(errno)); exit(EXIT_FAILURE); }
|
||||
|
||||
static sig_atomic_t sigwinch_arrived;
|
||||
|
||||
void handle_sigwinch(int signal) {
|
||||
if (signal == SIGWINCH) sigwinch_arrived = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wait_for_sigwinch() {
|
||||
sigwinch_arrived = 0;
|
||||
sigset_t mask, oldmask;
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handle_sigwinch;
|
||||
sa.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGWINCH, &sa, NULL) == -1) {
|
||||
exit_on_err("Failed to set the SIGWINCH signal handler");
|
||||
wait_for_terminal_ready(int fd) {
|
||||
char data;
|
||||
while(1) {
|
||||
int ret = read(fd, &data, 1);
|
||||
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||
break;
|
||||
}
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGWINCH);
|
||||
sigprocmask(SIG_BLOCK, &mask, &oldmask);
|
||||
while(!sigwinch_arrived) sigsuspend(&oldmask);
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
spawn(PyObject *self UNUSED, PyObject *args) {
|
||||
PyObject *argv_p, *env_p;
|
||||
int master, slave, stdin_read_fd, stdin_write_fd;
|
||||
int master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd;
|
||||
char *cwd, *exe;
|
||||
if (!PyArg_ParseTuple(args, "ssO!O!iiii", &exe, &cwd, &PyTuple_Type, &argv_p, &PyTuple_Type, &env_p, &master, &slave, &stdin_read_fd, &stdin_write_fd)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "ssO!O!iiiiii", &exe, &cwd, &PyTuple_Type, &argv_p, &PyTuple_Type, &env_p, &master, &slave, &stdin_read_fd, &stdin_write_fd, &ready_read_fd, &ready_write_fd)) return NULL;
|
||||
char name[2048] = {0};
|
||||
if (ttyname_r(slave, name, sizeof(name) - 1) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; }
|
||||
char **argv = serialize_string_tuple(argv_p);
|
||||
@ -98,8 +85,10 @@ spawn(PyObject *self UNUSED, PyObject *args) {
|
||||
#endif
|
||||
close(tfd);
|
||||
|
||||
// Wait for SIGWINCH which indicates kitty has setup the screen object
|
||||
wait_for_sigwinch();
|
||||
// Wait for READY_SIGNAL which indicates kitty has setup the screen object
|
||||
close(ready_write_fd);
|
||||
wait_for_terminal_ready(ready_read_fd);
|
||||
close(ready_read_fd);
|
||||
|
||||
// Redirect stdin/stdout/stderr to the pty
|
||||
if (dup2(slave, 1) == -1) exit_on_err("dup2() failed for fd number 1");
|
||||
|
@ -101,6 +101,8 @@ def fork(self):
|
||||
remove_cloexec(slave)
|
||||
fast_data_types.set_iutf8(master, True)
|
||||
stdin, self.stdin = self.stdin, None
|
||||
ready_read_fd, ready_write_fd = os.pipe()
|
||||
remove_cloexec(ready_read_fd)
|
||||
if stdin is not None:
|
||||
stdin_read_fd, stdin_write_fd = os.pipe()
|
||||
remove_cloexec(stdin_read_fd)
|
||||
@ -119,16 +121,22 @@ def fork(self):
|
||||
# Some macOS machines need the shell to have argv[0] prefixed by
|
||||
# hyphen, see https://github.com/kovidgoyal/kitty/issues/247
|
||||
argv[0] = ('-' + exe.split('/')[-1])
|
||||
pid = fast_data_types.spawn(exe, self.cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd)
|
||||
pid = fast_data_types.spawn(exe, self.cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd)
|
||||
os.close(slave)
|
||||
self.pid = pid
|
||||
self.child_fd = master
|
||||
if stdin is not None:
|
||||
os.close(stdin_read_fd)
|
||||
fast_data_types.thread_write(stdin_write_fd, stdin)
|
||||
os.close(ready_read_fd)
|
||||
self.terminal_ready_fd = ready_write_fd
|
||||
fcntl.fcntl(self.child_fd, fcntl.F_SETFL, fcntl.fcntl(self.child_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||
return pid
|
||||
|
||||
def mark_terminal_ready(self):
|
||||
os.close(self.terminal_ready_fd)
|
||||
self.terminal_ready_fd = -1
|
||||
|
||||
@property
|
||||
def cmdline(self):
|
||||
try:
|
||||
|
@ -16,13 +16,12 @@
|
||||
)
|
||||
from .fast_data_types import (
|
||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
||||
CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM,
|
||||
GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, OSC, REVERSE, SCROLL_FULL,
|
||||
SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, Screen, add_window,
|
||||
cell_size_for_window, compile_program, get_clipboard_string,
|
||||
glfw_post_empty_event, init_cell_program, set_clipboard_string,
|
||||
set_titlebar_color, set_window_render_data, update_window_title,
|
||||
update_window_visibility, viewport_for_window
|
||||
CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM, GRAPHICS_PREMULT_PROGRAM,
|
||||
GRAPHICS_PROGRAM, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE,
|
||||
STRIKETHROUGH, Screen, add_window, cell_size_for_window, compile_program,
|
||||
get_clipboard_string, glfw_post_empty_event, init_cell_program,
|
||||
set_clipboard_string, set_titlebar_color, set_window_render_data,
|
||||
update_window_title, update_window_visibility, viewport_for_window
|
||||
)
|
||||
from .keys import keyboard_mode_name
|
||||
from .rgb import to_color
|
||||
@ -104,6 +103,7 @@ class Window:
|
||||
def __init__(self, tab, child, opts, args, override_title=None):
|
||||
self.action_on_close = None
|
||||
self.layout_data = None
|
||||
self.pty_resized_once = False
|
||||
self.needs_attention = False
|
||||
self.override_title = override_title
|
||||
self.overlay_window_id = None
|
||||
@ -200,6 +200,9 @@ def set_geometry(self, window_idx, new_geometry):
|
||||
sg = self.update_position(new_geometry)
|
||||
self.needs_layout = False
|
||||
boss.child_monitor.resize_pty(self.id, *current_pty_size)
|
||||
if not self.pty_resized_once:
|
||||
self.pty_resized_once = True
|
||||
self.child.mark_terminal_ready()
|
||||
else:
|
||||
sg = self.update_position(new_geometry)
|
||||
self.geometry = g = new_geometry
|
||||
|
Loading…
Reference in New Issue
Block a user