Block handled signals early in startup before glfw is initialized to ensure that if the graphics libraries start a thread behind our backs, that threads defaults to haveing the signals blocked unless the library explicitly unblocks them. See #4636

This commit is contained in:
Kovid Goyal 2022-12-07 06:35:18 +05:30
parent 94410f2866
commit 9cb0e4d09d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 35 additions and 3 deletions

View File

@ -120,6 +120,34 @@ set_maximum_wait(monotonic_t val) {
if (val >= 0 && (val < maximum_wait || maximum_wait < 0)) maximum_wait = val; if (val >= 0 && (val < maximum_wait || maximum_wait < 0)) maximum_wait = val;
} }
#define KITTY_HANDLED_SIGNALS SIGINT, SIGHUP, SIGTERM, SIGCHLD, SIGUSR1, SIGUSR2, 0
static void
mask_variadic_signals(int sentinel, ...) {
// only need to mask signals when using SIGNAL_FD as signal actions are inherited by threads
// and only on Linux do we have reports of signals not being handled presumably because libwayland starts
// a thread behind our backs. See https://github.com/kovidgoyal/kitty/issues/4636
#ifdef HAS_SIGNAL_FD
sigset_t signals;
sigemptyset(&signals);
va_list valist;
va_start(valist, sentinel);
while (true) {
int sig = va_arg(valist, int);
if (sig == sentinel) break;
sigaddset(&signals, sig);
}
va_end(valist);
sigprocmask(SIG_BLOCK, &signals, NULL);
#endif
}
static PyObject*
mask_kitty_signals_process_wide(PyObject *self UNUSED, PyObject *a UNUSED) {
mask_variadic_signals(0, KITTY_HANDLED_SIGNALS);
Py_RETURN_NONE;
}
static PyObject * static PyObject *
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
ChildMonitor *self; ChildMonitor *self;
@ -138,7 +166,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
return NULL; return NULL;
} }
self = (ChildMonitor *)type->tp_alloc(type, 0); self = (ChildMonitor *)type->tp_alloc(type, 0);
if (!init_loop_data(&self->io_loop_data, SIGINT, SIGHUP, SIGTERM, SIGCHLD, SIGUSR1, SIGUSR2, 0)) return PyErr_SetFromErrno(PyExc_OSError); if (!init_loop_data(&self->io_loop_data, KITTY_HANDLED_SIGNALS)) return PyErr_SetFromErrno(PyExc_OSError);
self->talk_fd = talk_fd; self->talk_fd = talk_fd;
self->listen_fd = listen_fd; self->listen_fd = listen_fd;
self->prewarm_fd = prewarm_fd; self->prewarm_fd = prewarm_fd;
@ -1829,6 +1857,7 @@ static PyMethodDef module_methods[] = {
METHODB(monitor_pid, METH_VARARGS), METHODB(monitor_pid, METH_VARARGS),
METHODB(send_data_to_peer, METH_VARARGS), METHODB(send_data_to_peer, METH_VARARGS),
METHODB(cocoa_set_menubar_title, METH_VARARGS), METHODB(cocoa_set_menubar_title, METH_VARARGS),
METHODB(mask_kitty_signals_process_wide, METH_NOARGS),
{"sigqueue", (PyCFunction)sig_queue, METH_VARARGS, ""}, {"sigqueue", (PyCFunction)sig_queue, METH_VARARGS, ""},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };

View File

@ -1498,3 +1498,4 @@ def unicode_database_version() -> Tuple[int, int, int]: ...
def wrapped_kitten_names() -> List[str]: ... def wrapped_kitten_names() -> List[str]: ...
def expand_ansi_c_escapes(test: str) -> str: ... def expand_ansi_c_escapes(test: str) -> str: ...
def update_tab_bar_edge_colors(os_window_id: int) -> bool: ... def update_tab_bar_edge_colors(os_window_id: int) -> bool: ...
def mask_kitty_signals_process_wide() -> None: ...

View File

@ -21,8 +21,9 @@ from .constants import (
) )
from .fast_data_types import ( from .fast_data_types import (
GLFW_IBEAM_CURSOR, GLFW_MOD_ALT, GLFW_MOD_SHIFT, SingleKey, create_os_window, GLFW_IBEAM_CURSOR, GLFW_MOD_ALT, GLFW_MOD_SHIFT, SingleKey, create_os_window,
free_font_data, glfw_init, glfw_terminate, load_png_data, set_custom_cursor, free_font_data, glfw_init, glfw_terminate, load_png_data,
set_default_window_icon, set_options, mask_kitty_signals_process_wide, set_custom_cursor, set_default_window_icon,
set_options,
) )
from .fonts.box_drawing import set_scale from .fonts.box_drawing import set_scale
from .fonts.render import set_font_family from .fonts.render import set_font_family
@ -102,6 +103,7 @@ def init_glfw_module(glfw_module: str, debug_keyboard: bool = False, debug_rende
def init_glfw(opts: Options, debug_keyboard: bool = False, debug_rendering: bool = False) -> str: def init_glfw(opts: Options, debug_keyboard: bool = False, debug_rendering: bool = False) -> str:
mask_kitty_signals_process_wide()
glfw_module = 'cocoa' if is_macos else ('wayland' if is_wayland(opts) else 'x11') glfw_module = 'cocoa' if is_macos else ('wayland' if is_wayland(opts) else 'x11')
init_glfw_module(glfw_module, debug_keyboard, debug_rendering) init_glfw_module(glfw_module, debug_keyboard, debug_rendering)
return glfw_module return glfw_module