mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-21 11:39:57 +03:00
Fix regression in 0.26.0 that caused launching kitty without working STDIO handles to result in high CPU usage and prewarming failing
Fixes #5444
This commit is contained in:
parent
bb2ec9cde7
commit
6604e0d015
@ -40,6 +40,8 @@ Detailed list of changes
|
||||
|
||||
- hyperlinked_grep kitten: Allow control which parts of rg output are hyperlinked (:pull:`5428`)
|
||||
|
||||
- Fix regression in 0.26.0 that caused launching kitty without working STDIO handles to result in high CPU usage and prewarming failing (:iss:`5444`)
|
||||
|
||||
0.26.1 [2022-08-30]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <stdint.h>
|
||||
#include <wchar.h>
|
||||
#include <Python.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef KITTY_LIB_PATH
|
||||
#define KITTY_LIB_PATH "../.."
|
||||
@ -268,9 +269,55 @@ read_exe_path(char *exe, size_t buf_sz) {
|
||||
}
|
||||
#endif // }}}
|
||||
|
||||
static bool
|
||||
is_valid_fd(int fd)
|
||||
{
|
||||
// This is copied from the python source code as we need the exact same semantics
|
||||
// to prevent python from giving us None for sys.stdout and friends.
|
||||
#if defined(F_GETFD) && ( \
|
||||
defined(__linux__) || \
|
||||
defined(__APPLE__) || \
|
||||
defined(__wasm__))
|
||||
return fcntl(fd, F_GETFD) >= 0;
|
||||
#elif defined(__linux__)
|
||||
int fd2 = dup(fd);
|
||||
if (fd2 >= 0) {
|
||||
close(fd2);
|
||||
}
|
||||
return (fd2 >= 0);
|
||||
#else
|
||||
struct stat st;
|
||||
return (fstat(fd, &st) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
reopen_to_null(const char *mode, FILE *stream) {
|
||||
errno = 0;
|
||||
while (true) {
|
||||
if (freopen("/dev/null", mode, stream) != NULL) return true;
|
||||
if (errno == EINTR) continue;
|
||||
perror("Failed to re-open STDIO handle to /dev/null");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ensure_working_stdio(void) {
|
||||
#define C(which, mode) { \
|
||||
int fd = fileno(which); \
|
||||
if (fd < 0) { if (!reopen_to_null(mode, which)) return false; } \
|
||||
else if (!is_valid_fd(fd)) { \
|
||||
close(fd); if (!reopen_to_null(mode, which)) return false; \
|
||||
}}
|
||||
C(stdin, "r") C(stdout, "w") C(stderr, "w")
|
||||
return true;
|
||||
#undef C
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char* envp[]) {
|
||||
if (argc < 1 || !argv) { fprintf(stderr, "Invalid argc/argv\n"); return 1; }
|
||||
if (!ensure_working_stdio()) return 1;
|
||||
char exe[PATH_MAX+1] = {0};
|
||||
char exe_dir_buf[PATH_MAX+1] = {0};
|
||||
FREE_AFTER_FUNCTION const char *lc_ctype = NULL;
|
||||
|
@ -107,6 +107,22 @@ def t(x, e):
|
||||
run_tests(partial(docs_url, local_docs_root=None), w, '/')
|
||||
self.ae(docs_url('#ref=issues-123'), 'https://github.com/kovidgoyal/kitty/issues/123')
|
||||
|
||||
def test_launcher_ensures_stdio(self):
|
||||
from kitty.constants import kitty_exe
|
||||
import subprocess
|
||||
exe = kitty_exe()
|
||||
cp = subprocess.run([exe, '+runpy', '''\
|
||||
import os, sys
|
||||
if sys.stdin:
|
||||
os.close(sys.stdin.fileno())
|
||||
if sys.stdout:
|
||||
os.close(sys.stdout.fileno())
|
||||
if sys.stderr:
|
||||
os.close(sys.stderr.fileno())
|
||||
os.execlp('kitty', 'kitty', '+runpy', 'import sys; raise SystemExit(1 if sys.stdout is None or sys.stdin is None or sys.stderr is None else 0)')
|
||||
'''])
|
||||
self.assertEqual(cp.returncode, 0)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestBuild)
|
||||
|
Loading…
Reference in New Issue
Block a user