From 7a31c7ff5033b7fc3b593875c7b5d14d6c2fac19 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 7 Jun 2022 20:37:55 +0530 Subject: [PATCH] Start work on everywhere prewarm --- launcher.c | 12 ++++------ prewarm-launcher.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 prewarm-launcher.h diff --git a/launcher.c b/launcher.c index ef6e95422..1875bec50 100644 --- a/launcher.c +++ b/launcher.c @@ -5,13 +5,9 @@ * Distributed under terms of the GPL3 license. */ -#include -#include -#include +#include "prewarm-launcher.h" + #include -#include -#include -#include #ifdef __APPLE__ #include #include @@ -19,9 +15,8 @@ #else #include #endif -#include #include -#include +#include #ifndef KITTY_LIB_PATH #define KITTY_LIB_PATH "../.." @@ -275,6 +270,7 @@ read_exe_path(char *exe, size_t buf_sz) { int main(int argc, char *argv[]) { if (argc < 1 || !argv) { fprintf(stderr, "Invalid argc/argv\n"); return 1; } + use_prewarmed_process(argc, argv); char exe[PATH_MAX+1] = {0}; char exe_dir_buf[PATH_MAX+1] = {0}; FREE_AFTER_FUNCTION const char *lc_ctype = NULL; diff --git a/prewarm-launcher.h b/prewarm-launcher.h new file mode 100644 index 000000000..a69660993 --- /dev/null +++ b/prewarm-launcher.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#pragma once + +// needed for strnlen +#define _XOPEN_SOURCE 700 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +connect_to_socket_synchronously(const char *addr) { + struct sockaddr_un sock_addr = {.sun_family=AF_UNIX}; + strncpy(sock_addr.sun_path, addr, sizeof(sock_addr.sun_path) - 1); + const size_t addrlen = strnlen(sock_addr.sun_path, sizeof(sock_addr.sun_path)) + sizeof(sock_addr.sun_family); + if (sock_addr.sun_path[0] == '@') sock_addr.sun_path[0] = 0; + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (connect(fd, (struct sockaddr*)&sock_addr, addrlen) != 0) { + if (errno != EINTR) return -1; + struct pollfd poll_data = {.fd=fd, .events=POLLOUT}; + while (poll (&poll_data, 1, -1) == -1) { if (errno != EINTR) return -1; } + int socket_error_code = 0; + socklen_t sizeof_socket_error_code = sizeof(socket_error_code); + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &socket_error_code, &sizeof_socket_error_code) == -1) return -1; + if (socket_error_code != 0) return -1; + } + return fd; +} + +static bool +is_prewarmable(int argc, char *argv[]) { + if (argc < 2) return false; + if (argv[1][0] != '+') return false; + if (argv[1][1] != 0) return strcmp(argv[1], "+open") != 0; + if (argc < 3) return false; + return strcmp(argv[2], "open") != 0; +} + +static void +use_prewarmed_process(int argc, char *argv[]) { + const char *env_addr = getenv("KITTY_PREWARM_SOCKET_ADDRESS"); + if (!env_addr || !*env_addr || !is_prewarmable(argc, argv)) return; + int fd = connect_to_socket_synchronously(env_addr); + if (fd < 0) return; +} diff --git a/setup.py b/setup.py index 2239670cd..2762adb2b 100755 --- a/setup.py +++ b/setup.py @@ -870,7 +870,7 @@ def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 's src, '-o', dest] + ldflags + libs + pylib key = CompileKey('launcher.c', 'kitty') desc = f'Building {emphasis("launcher")} ...' - args.compilation_database.add_command(desc, cmd, partial(newer, dest, src), key=key, keyfile=src) + args.compilation_database.add_command(desc, cmd, partial(newer, dest, src, "prewarm-launcher.h"), key=key, keyfile=src) args.compilation_database.build_all()