diff --git a/kitty/data-types.c b/kitty/data-types.c index 743f1afbc..3af625b5a 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -341,6 +341,10 @@ PyInit_fast_data_types(void) { PyModule_AddIntMacro(m, APC); PyModule_AddIntMacro(m, OSC); PyModule_AddIntMacro(m, FILE_TRANSFER_CODE); + // FreeBSD's man page says this is 1023. Linux says its PATH_MAX. + // Apple says its SHM_NAME_MAX but SHM_NAME_MAX is not actually declared in typical CrApple style. + // Experimentation shows that 1023 is allowed on macOS Catalina + PyModule_AddIntConstant(m, "SHM_NAME_MAX", MIN(1023, PATH_MAX)); return m; } diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index a76129980..c17c11736 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -12,6 +12,7 @@ from kitty.marks import MarkerFunc from kitty.options.types import Options # Constants {{{ +SHM_NAME_MAX: int MOUSE_SELECTION_LINE: int MOUSE_SELECTION_EXTEND: int MOUSE_SELECTION_NORMAL: int diff --git a/kitty/shm.py b/kitty/shm.py index 4c610a17d..fac2f346f 100644 --- a/kitty/shm.py +++ b/kitty/shm.py @@ -1,20 +1,27 @@ #!/usr/bin/env python # License: GPLv3 Copyright: 2022, Kovid Goyal -# This is present in the python stdlib after version 3.7 but we need to support -# 3.7 for another year, so sigh. +# This is present in the python stdlib (version 3.7) in +# multiprocessing.shared_memory. However, it is crippled in various ways, most +# notably using extremely small filenames. import mmap import os import secrets +import stat from typing import Optional -from kitty.fast_data_types import shm_open, shm_unlink +from kitty.fast_data_types import SHM_NAME_MAX, shm_open, shm_unlink -def make_filename(safe_length: int = 14, prefix: str = '/ky-') -> str: +def make_filename(prefix: str) -> str: "Create a random filename for the shared memory object." - # number of random bytes to use for name + # number of random bytes to use for name. Use a largeish value + # to make double unlink safe. + safe_length = min(128, SHM_NAME_MAX) + if not prefix.startswith('/'): + # FreeBSD requires name to start with / + prefix = '/' + prefix nbytes = (safe_length - len(prefix)) // 2 name = prefix + secrets.token_hex(nbytes) return name @@ -24,7 +31,11 @@ class SharedMemory: _buf: Optional[memoryview] = None _fd: int = -1 - def __init__(self, name: Optional[str] = None, create: bool = False, size: int = 0, readonly: bool = False, mode: int = 0o600): + def __init__( + self, name: Optional[str] = None, create: bool = False, size: int = 0, readonly: bool = False, + mode: int = stat.S_IREAD | stat.S_IWRITE, + prefix: str = 'kitty-' + ): if not size >= 0: raise ValueError("'size' must be a positive integer") if create: @@ -39,7 +50,7 @@ class SharedMemory: if name is None: while True: - name = make_filename() + name = make_filename(prefix) try: self._fd = shm_open(name, flags, mode) except FileExistsError: