From 2c00a68624d4e37b30048af3701ec3ab5381c24f Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 30 Jun 2025 22:22:20 +0200 Subject: [PATCH] libutil: explicitly declare and document our reserved signals Change-Id: Ia27cce0d3577219b7476f7ce6dade4387ba727b2 --- lix/libmain/shared.cc | 12 +++++------- lix/libstore/pathlocks.cc | 6 +++--- lix/libutil/signals.hh | 17 ++++++++++++++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lix/libmain/shared.cc b/lix/libmain/shared.cc index 1dd3b93d4..5ac7df087 100644 --- a/lix/libmain/shared.cc +++ b/lix/libmain/shared.cc @@ -130,11 +130,7 @@ static void sigHandler(int signo) { } void initNix() { - // kj needs a signal for internal use. no system lix habitually runs on causes - // kj to actually *use* this signal, but better safe than sorry—and since some - // OSes (*cough* macos) don't support realtime signals we must use SIGUSR2 for - // this, thus "consuming" both USR signals. at some point we will change this. - kj::UnixEventPort::setReservedSignal(SIGUSR2); + kj::UnixEventPort::setReservedSignal(KJ_RESERVED_SIGNAL); registerCrashHandler(); @@ -155,9 +151,11 @@ void initNix() if (sigaction(SIGCHLD, &act, 0)) throw SysError("resetting SIGCHLD"); - /* Install a dummy SIGUSR1 handler for use with pthread_kill(). */ + /* Install a dummy INTERRUPT_NOTIFY_SIGNAL handler for use with pthread_kill(). */ act.sa_handler = sigHandler; - if (sigaction(SIGUSR1, &act, 0)) throw SysError("handling SIGUSR1"); + if (sigaction(INTERRUPT_NOTIFY_SIGNAL, &act, 0)) { + throw SysError("handling interrupt notify signal %i", INTERRUPT_NOTIFY_SIGNAL); + } #if __APPLE__ /* HACK: on darwin, we need can’t use sigprocmask with SIGWINCH. diff --git a/lix/libstore/pathlocks.cc b/lix/libstore/pathlocks.cc index e2e892187..61b140a56 100644 --- a/lix/libstore/pathlocks.cc +++ b/lix/libstore/pathlocks.cc @@ -48,8 +48,8 @@ void lockFile(int fd, LockType lockType, NeverAsync) static kj::Promise> lockFileAsyncInner(int fd, LockType lockType) try { - // start a thread to lock the file synchronously, waiting for SIGUSR1 to signal - // that the call was canceled. SIGUSR1 is already set aside for such signaling. + // start a thread to lock the file synchronously, waiting for an + // INTERRUPT_NOTIFY_SIGNAL to signal that the call was canceled. int type = convertLockType(lockType); auto pfp = kj::newPromiseAndCrossThreadFulfiller>(); @@ -64,7 +64,7 @@ try { pfp.fulfiller->fulfill(result::success()); }); auto cancel = kj::defer([&] { - pthread_kill(locker.native_handle(), SIGUSR1); + pthread_kill(locker.native_handle(), INTERRUPT_NOTIFY_SIGNAL); locker.join(); }); diff --git a/lix/libutil/signals.hh b/lix/libutil/signals.hh index 12d8ced62..919a8eb55 100644 --- a/lix/libutil/signals.hh +++ b/lix/libutil/signals.hh @@ -35,6 +35,16 @@ namespace nix { +/// reserved signal used to notify threads of interruption requests, e.g. users +/// pressing Control-C on the terminal. we purposely do not use SIGINT handlers +/// provided by the OS to allow for more orderly cleanup of running operations. +static inline constexpr int INTERRUPT_NOTIFY_SIGNAL = SIGUSR1; +/// kj needs a signal for internal use. no system lix habitually runs on causes +/// kj to actually *use* this signal, but better safe than sorry—and since some +/// OSes (*cough* macos) don't support realtime signals we must use SIGUSR2 for +/// this, thus "consuming" both USR signals. at some point we will change this. +static inline constexpr int KJ_RESERVED_SIGNAL = SIGUSR2; + /* User interruption. */ class Interrupted; @@ -124,7 +134,7 @@ kj::Promise> makeInterruptible(kj::Promise> p) void triggerInterrupt(); /** - * A RAII class that causes the current thread to receive SIGUSR1 when + * A RAII class that causes the current thread to receive `INTERRUPT_NOTIFY_SIGNAL` when * the signal handler thread receives SIGINT. That is, this allows * SIGINT to be multiplexed to multiple threads. */ @@ -135,8 +145,9 @@ struct ReceiveInterrupts ReceiveInterrupts() : target(pthread_self()) - , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) - { } + , callback(createInterruptCallback([&] { pthread_kill(target, INTERRUPT_NOTIFY_SIGNAL); })) + { + } }; };