diff options
32 files changed, 310 insertions, 251 deletions
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 20567f840..5268ce44b 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -40,6 +40,7 @@ extern "C" { #include "finally.hh" #include "markdown.hh" #include "local-fs-store.hh" +#include "signals.hh" #include "print.hh" #if HAVE_BOEHMGC diff --git a/src/libexpr/print-ambiguous.cc b/src/libexpr/print-ambiguous.cc index 5355dff65..eaba02122 100644 --- a/src/libexpr/print-ambiguous.cc +++ b/src/libexpr/print-ambiguous.cc @@ -1,6 +1,7 @@ #include "print-ambiguous.hh" #include "print.hh" #include "eval.hh" +#include "signals.hh" namespace nix { diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index df79718fb..7ef21dfa9 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -5,6 +5,7 @@ #include "ansicolor.hh" #include "store-api.hh" #include "english.hh" +#include "signals.hh" #include "eval.hh" namespace nix { diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc index 787a46426..ebb3379a8 100644 --- a/src/libexpr/value-to-json.cc +++ b/src/libexpr/value-to-json.cc @@ -1,6 +1,7 @@ #include "value-to-json.hh" #include "eval-inline.hh" #include "util.hh" +#include "signals.hh" #include "store-api.hh" #include <cstdlib> diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index 2539ad1c1..5d1fbd28d 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -2,6 +2,7 @@ #include "xml-writer.hh" #include "eval-inline.hh" #include "util.hh" +#include "signals.hh" #include <cstdlib> diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 4ad1faec3..6d851d776 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -3,6 +3,7 @@ #include "store-api.hh" #include "gc-store.hh" #include "util.hh" +#include "signals.hh" #include "loggers.hh" #include "progress-bar.hh" diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index b4fea693f..2e1f84859 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -10,6 +10,7 @@ #include "nar-info-disk-cache.hh" #include "nar-accessor.hh" #include "thread-pool.hh" +#include "signals.hh" #include "callback.hh" #include <chrono> diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index e77772f96..d8d9ba283 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -1,6 +1,7 @@ #include "worker.hh" #include "substitution-goal.hh" #include "nar-info.hh" +#include "signals.hh" #include "finally.hh" namespace nix { diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index d6bcba3ff..83167b0f3 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -3,6 +3,7 @@ #include "substitution-goal.hh" #include "drv-output-substitution-goal.hh" #include "local-derivation-goal.hh" +#include "signals.hh" #include "hook-instance.hh" #include <poll.h> diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 0d09fff98..5664579e7 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -3,6 +3,7 @@ #include "globals.hh" #include "store-api.hh" #include "s3.hh" +#include "signals.hh" #include "compression.hh" #include "finally.hh" #include "callback.hh" diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index ac61f7f53..bd9be52f3 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -1,6 +1,7 @@ #include "derivations.hh" #include "globals.hh" #include "local-store.hh" +#include "signals.hh" #include "finally.hh" #include <functional> diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 78ca79c89..ecaab8f37 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -8,6 +8,7 @@ #include "references.hh" #include "callback.hh" #include "topo-sort.hh" +#include "signals.hh" #include "finally.hh" #include "compression.hh" diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 4a79cf4a1..e09072e90 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -1,6 +1,7 @@ #include "util.hh" #include "local-store.hh" #include "globals.hh" +#include "signals.hh" #include <cstdlib> #include <cstring> diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc index adc763e6a..955ae3a34 100644 --- a/src/libstore/pathlocks.cc +++ b/src/libstore/pathlocks.cc @@ -1,5 +1,6 @@ #include "pathlocks.hh" #include "util.hh" +#include "signals.hh" #include "sync.hh" #include <cerrno> diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 58fac40dc..7572473cf 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -1,5 +1,6 @@ #include "serialise.hh" #include "util.hh" +#include "signals.hh" #include "path-with-outputs.hh" #include "gc-store.hh" #include "remote-fs-accessor.hh" diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc index 365794bd3..4bd425b46 100644 --- a/src/libstore/sqlite.cc +++ b/src/libstore/sqlite.cc @@ -1,6 +1,7 @@ #include "sqlite.hh" #include "globals.hh" #include "util.hh" +#include "signals.hh" #include "url.hh" #include <sqlite3.h> diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 9a6c920f7..94202d46e 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -11,6 +11,7 @@ #include "archive.hh" #include "callback.hh" #include "remote-store.hh" +#include "signals.hh" // FIXME this should not be here, see TODO below on // `addMultipleToStore`. #include "worker-protocol.hh" diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index ce10a35ae..e3ff7345f 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -14,6 +14,7 @@ #include "archive.hh" #include "util.hh" #include "config.hh" +#include "signals.hh" namespace nix { diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index ba0847cde..575a03712 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -2,6 +2,7 @@ #include "tarfile.hh" #include "util.hh" #include "finally.hh" +#include "signals.hh" #include "logging.hh" #include <archive.h> diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc index 2a7787c0e..ea934ffaf 100644 --- a/src/libutil/filesystem.cc +++ b/src/libutil/filesystem.cc @@ -4,6 +4,7 @@ #include "finally.hh" #include "util.hh" +#include "signals.hh" #include "types.hh" namespace fs = std::filesystem; diff --git a/src/libutil/monitor-fd.hh b/src/libutil/monitor-fd.hh index 86d0115fc..228fb13f8 100644 --- a/src/libutil/monitor-fd.hh +++ b/src/libutil/monitor-fd.hh @@ -10,6 +10,8 @@ #include <unistd.h> #include <signal.h> +#include "signals.hh" + namespace nix { diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 3d9dcf728..692144b75 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -1,5 +1,6 @@ #include "serialise.hh" #include "util.hh" +#include "signals.hh" #include <cstring> #include <cerrno> diff --git a/src/libutil/signals.cc b/src/libutil/signals.cc new file mode 100644 index 000000000..f5c79b325 --- /dev/null +++ b/src/libutil/signals.cc @@ -0,0 +1,184 @@ +#include "signals.hh" +#include "util.hh" +#include "error.hh" +#include "sync.hh" + +#include <thread> + +namespace nix { + +std::atomic<bool> _isInterrupted = false; + +static thread_local bool interruptThrown = false; +thread_local std::function<bool()> interruptCheck; + +void setInterruptThrown() +{ + interruptThrown = true; +} + +void _interrupted() +{ + /* Block user interrupts while an exception is being handled. + Throwing an exception while another exception is being handled + kills the program! */ + if (!interruptThrown && !std::uncaught_exceptions()) { + interruptThrown = true; + throw Interrupted("interrupted by the user"); + } +} + + +////////////////////////////////////////////////////////////////////// + +/* We keep track of interrupt callbacks using integer tokens, so we can iterate + safely without having to lock the data structure while executing arbitrary + functions. + */ +struct InterruptCallbacks { + typedef int64_t Token; + + /* We use unique tokens so that we can't accidentally delete the wrong + handler because of an erroneous double delete. */ + Token nextToken = 0; + + /* Used as a list, see InterruptCallbacks comment. */ + std::map<Token, std::function<void()>> callbacks; +}; + +static Sync<InterruptCallbacks> _interruptCallbacks; + +static void signalHandlerThread(sigset_t set) +{ + while (true) { + int signal = 0; + sigwait(&set, &signal); + + if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) + triggerInterrupt(); + + else if (signal == SIGWINCH) { + updateWindowSize(); + } + } +} + +void triggerInterrupt() +{ + _isInterrupted = true; + + { + InterruptCallbacks::Token i = 0; + while (true) { + std::function<void()> callback; + { + auto interruptCallbacks(_interruptCallbacks.lock()); + auto lb = interruptCallbacks->callbacks.lower_bound(i); + if (lb == interruptCallbacks->callbacks.end()) + break; + + callback = lb->second; + i = lb->first + 1; + } + + try { + callback(); + } catch (...) { + ignoreException(); + } + } + } +} + +static sigset_t savedSignalMask; +static bool savedSignalMaskIsSet = false; + +void setChildSignalMask(sigset_t * sigs) +{ + assert(sigs); // C style function, but think of sigs as a reference + +#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE + sigemptyset(&savedSignalMask); + // There's no "assign" or "copy" function, so we rely on (math) idempotence + // of the or operator: a or a = a. + sigorset(&savedSignalMask, sigs, sigs); +#else + // Without sigorset, our best bet is to assume that sigset_t is a type that + // can be assigned directly, such as is the case for a sigset_t defined as + // an integer type. + savedSignalMask = *sigs; +#endif + + savedSignalMaskIsSet = true; +} + +void saveSignalMask() { + if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) + throw SysError("querying signal mask"); + + savedSignalMaskIsSet = true; +} + +void startSignalHandlerThread() +{ + updateWindowSize(); + + saveSignalMask(); + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGPIPE); + sigaddset(&set, SIGWINCH); + if (pthread_sigmask(SIG_BLOCK, &set, nullptr)) + throw SysError("blocking signals"); + + std::thread(signalHandlerThread, set).detach(); +} + +void restoreSignals() +{ + // If startSignalHandlerThread wasn't called, that means we're not running + // in a proper libmain process, but a process that presumably manages its + // own signal handlers. Such a process should call either + // - initNix(), to be a proper libmain process + // - startSignalHandlerThread(), to resemble libmain regarding signal + // handling only + // - saveSignalMask(), for processes that define their own signal handling + // thread + // TODO: Warn about this? Have a default signal mask? The latter depends on + // whether we should generally inherit signal masks from the caller. + // I don't know what the larger unix ecosystem expects from us here. + if (!savedSignalMaskIsSet) + return; + + if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) + throw SysError("restoring signals"); +} + +/* RAII helper to automatically deregister a callback. */ +struct InterruptCallbackImpl : InterruptCallback +{ + InterruptCallbacks::Token token; + ~InterruptCallbackImpl() override + { + auto interruptCallbacks(_interruptCallbacks.lock()); + interruptCallbacks->callbacks.erase(token); + } +}; + +std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()> callback) +{ + auto interruptCallbacks(_interruptCallbacks.lock()); + auto token = interruptCallbacks->nextToken++; + interruptCallbacks->callbacks.emplace(token, callback); + + auto res = std::make_unique<InterruptCallbackImpl>(); + res->token = token; + + return std::unique_ptr<InterruptCallback>(res.release()); +} + +}; diff --git a/src/libutil/signals.hh b/src/libutil/signals.hh new file mode 100644 index 000000000..c58dc37cf --- /dev/null +++ b/src/libutil/signals.hh @@ -0,0 +1,93 @@ +#pragma once +/// @file + +#include "types.hh" +#include "error.hh" + +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <signal.h> + +#include <atomic> +#include <functional> +#include <sstream> + +namespace nix { + +/* User interruption. */ + +extern std::atomic<bool> _isInterrupted; + +extern thread_local std::function<bool()> interruptCheck; + +void setInterruptThrown(); + +void _interrupted(); + +void inline checkInterrupt() +{ + if (_isInterrupted || (interruptCheck && interruptCheck())) + _interrupted(); +} + +MakeError(Interrupted, BaseError); + +void restoreSignals(); + + +/** + * Start a thread that handles various signals. Also block those signals + * on the current thread (and thus any threads created by it). + * Saves the signal mask before changing the mask to block those signals. + * See saveSignalMask(). + */ +void startSignalHandlerThread(); + +/** + * Saves the signal mask, which is the signal mask that nix will restore + * before creating child processes. + * See setChildSignalMask() to set an arbitrary signal mask instead of the + * current mask. + */ +void saveSignalMask(); + +/** + * Sets the signal mask. Like saveSignalMask() but for a signal set that doesn't + * necessarily match the current thread's mask. + * See saveSignalMask() to set the saved mask to the current mask. + */ +void setChildSignalMask(sigset_t *sigs); + +struct InterruptCallback +{ + virtual ~InterruptCallback() { }; +}; + +/** + * Register a function that gets called on SIGINT (in a non-signal + * context). + */ +std::unique_ptr<InterruptCallback> createInterruptCallback( + std::function<void()> callback); + +void triggerInterrupt(); + +/** + * A RAII class that causes the current thread to receive SIGUSR1 when + * the signal handler thread receives SIGINT. That is, this allows + * SIGINT to be multiplexed to multiple threads. + */ +struct ReceiveInterrupts +{ + pthread_t target; + std::unique_ptr<InterruptCallback> callback; + + ReceiveInterrupts() + : target(pthread_self()) + , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) + { } +}; + +}; diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 6513234ba..c6ffa75f2 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -1,4 +1,5 @@ #include "thread-pool.hh" +#include "signals.hh" namespace nix { diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 007ec8bef..9bb769fc2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -3,6 +3,7 @@ #include "finally.hh" #include "serialise.hh" #include "cgroup.hh" +#include "signals.hh" #include <array> #include <cctype> @@ -1361,31 +1362,6 @@ void closeOnExec(int fd) ////////////////////////////////////////////////////////////////////// -std::atomic<bool> _isInterrupted = false; - -static thread_local bool interruptThrown = false; -thread_local std::function<bool()> interruptCheck; - -void setInterruptThrown() -{ - interruptThrown = true; -} - -void _interrupted() -{ - /* Block user interrupts while an exception is being handled. - Throwing an exception while another exception is being handled - kills the program! */ - if (!interruptThrown && !std::uncaught_exceptions()) { - interruptThrown = true; - throw Interrupted("interrupted by the user"); - } -} - - -////////////////////////////////////////////////////////////////////// - - template<class C> C tokenizeString(std::string_view s, std::string_view separators) { C result; @@ -1717,7 +1693,7 @@ std::pair<std::string_view, std::string_view> getLine(std::string_view s) static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}}; -static void updateWindowSize() +void updateWindowSize() { struct winsize ws; if (ioctl(2, TIOCGWINSZ, &ws) == 0) { @@ -1734,133 +1710,6 @@ std::pair<unsigned short, unsigned short> getWindowSize() } -/* We keep track of interrupt callbacks using integer tokens, so we can iterate - safely without having to lock the data structure while executing arbitrary - functions. - */ -struct InterruptCallbacks { - typedef int64_t Token; - - /* We use unique tokens so that we can't accidentally delete the wrong - handler because of an erroneous double delete. */ - Token nextToken = 0; - - /* Used as a list, see InterruptCallbacks comment. */ - std::map<Token, std::function<void()>> callbacks; -}; - -static Sync<InterruptCallbacks> _interruptCallbacks; - -static void signalHandlerThread(sigset_t set) -{ - while (true) { - int signal = 0; - sigwait(&set, &signal); - - if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) - triggerInterrupt(); - - else if (signal == SIGWINCH) { - updateWindowSize(); - } - } -} - -void triggerInterrupt() -{ - _isInterrupted = true; - - { - InterruptCallbacks::Token i = 0; - while (true) { - std::function<void()> callback; - { - auto interruptCallbacks(_interruptCallbacks.lock()); - auto lb = interruptCallbacks->callbacks.lower_bound(i); - if (lb == interruptCallbacks->callbacks.end()) - break; - - callback = lb->second; - i = lb->first + 1; - } - - try { - callback(); - } catch (...) { - ignoreException(); - } - } - } -} - -static sigset_t savedSignalMask; -static bool savedSignalMaskIsSet = false; - -void setChildSignalMask(sigset_t * sigs) -{ - assert(sigs); // C style function, but think of sigs as a reference - -#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE - sigemptyset(&savedSignalMask); - // There's no "assign" or "copy" function, so we rely on (math) idempotence - // of the or operator: a or a = a. - sigorset(&savedSignalMask, sigs, sigs); -#else - // Without sigorset, our best bet is to assume that sigset_t is a type that - // can be assigned directly, such as is the case for a sigset_t defined as - // an integer type. - savedSignalMask = *sigs; -#endif - - savedSignalMaskIsSet = true; -} - -void saveSignalMask() { - if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) - throw SysError("querying signal mask"); - - savedSignalMaskIsSet = true; -} - -void startSignalHandlerThread() -{ - updateWindowSize(); - - saveSignalMask(); - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGTERM); - sigaddset(&set, SIGHUP); - sigaddset(&set, SIGPIPE); - sigaddset(&set, SIGWINCH); - if (pthread_sigmask(SIG_BLOCK, &set, nullptr)) - throw SysError("blocking signals"); - - std::thread(signalHandlerThread, set).detach(); -} - -static void restoreSignals() -{ - // If startSignalHandlerThread wasn't called, that means we're not running - // in a proper libmain process, but a process that presumably manages its - // own signal handlers. Such a process should call either - // - initNix(), to be a proper libmain process - // - startSignalHandlerThread(), to resemble libmain regarding signal - // handling only - // - saveSignalMask(), for processes that define their own signal handling - // thread - // TODO: Warn about this? Have a default signal mask? The latter depends on - // whether we should generally inherit signal masks from the caller. - // I don't know what the larger unix ecosystem expects from us here. - if (!savedSignalMaskIsSet) - return; - - if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) - throw SysError("restoring signals"); -} - rlim_t savedStackSize = 0; void setStackSize(rlim_t stackSize) @@ -1951,30 +1800,6 @@ void restoreProcessContext(bool restoreMounts) } } -/* RAII helper to automatically deregister a callback. */ -struct InterruptCallbackImpl : InterruptCallback -{ - InterruptCallbacks::Token token; - ~InterruptCallbackImpl() override - { - auto interruptCallbacks(_interruptCallbacks.lock()); - interruptCallbacks->callbacks.erase(token); - } -}; - -std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()> callback) -{ - auto interruptCallbacks(_interruptCallbacks.lock()); - auto token = interruptCallbacks->nextToken++; - interruptCallbacks->callbacks.emplace(token, callback); - - auto res = std::make_unique<InterruptCallbackImpl>(); - res->token = token; - - return std::unique_ptr<InterruptCallback>(res.release()); -} - - AutoCloseFD createUnixDomainSocket() { AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM diff --git a/src/libutil/util.hh b/src/libutil/util.hh index acd77ee33..ed4c8705a 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -516,25 +516,6 @@ void closeMostFDs(const std::set<int> & exceptions); void closeOnExec(int fd); -/* User interruption. */ - -extern std::atomic<bool> _isInterrupted; - -extern thread_local std::function<bool()> interruptCheck; - -void setInterruptThrown(); - -void _interrupted(); - -void inline checkInterrupt() -{ - if (_isInterrupted || (interruptCheck && interruptCheck())) - _interrupted(); -} - -MakeError(Interrupted, BaseError); - - MakeError(FormatError, Error); @@ -830,61 +811,6 @@ class Callback; /** - * Start a thread that handles various signals. Also block those signals - * on the current thread (and thus any threads created by it). - * Saves the signal mask before changing the mask to block those signals. - * See saveSignalMask(). - */ -void startSignalHandlerThread(); - -/** - * Saves the signal mask, which is the signal mask that nix will restore - * before creating child processes. - * See setChildSignalMask() to set an arbitrary signal mask instead of the - * current mask. - */ -void saveSignalMask(); - -/** - * Sets the signal mask. Like saveSignalMask() but for a signal set that doesn't - * necessarily match the current thread's mask. - * See saveSignalMask() to set the saved mask to the current mask. - */ -void setChildSignalMask(sigset_t *sigs); - -struct InterruptCallback -{ - virtual ~InterruptCallback() { }; -}; - -/** - * Register a function that gets called on SIGINT (in a non-signal - * context). - */ -std::unique_ptr<InterruptCallback> createInterruptCallback( - std::function<void()> callback); - -void triggerInterrupt(); - -/** - * A RAII class that causes the current thread to receive SIGUSR1 when - * the signal handler thread receives SIGINT. That is, this allows - * SIGINT to be multiplexed to multiple threads. - */ -struct ReceiveInterrupts -{ - pthread_t target; - std::unique_ptr<InterruptCallback> callback; - - ReceiveInterrupts() - : target(pthread_self()) - , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) - { } -}; - - - -/** * A RAII helper that increments a counter on construction and * decrements it on destruction. */ @@ -903,6 +829,8 @@ struct MaintainCount */ std::pair<unsigned short, unsigned short> getWindowSize(); +void updateWindowSize(); + /** * Used in various places. diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc index 70af53b28..1cbba0537 100644 --- a/src/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix-collect-garbage/nix-collect-garbage.cc @@ -5,6 +5,7 @@ #include "shared.hh" #include "globals.hh" #include "legacy.hh" +#include "signals.hh" #include <iostream> #include <cerrno> diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc index f2eea2cf4..42ce3b996 100644 --- a/src/nix/daemon.cc +++ b/src/nix/daemon.cc @@ -12,6 +12,7 @@ #include "derivations.hh" #include "finally.hh" #include "legacy.hh" +#include "signals.hh" #include "daemon.hh" #include <algorithm> diff --git a/src/nix/optimise-store.cc b/src/nix/optimise-store.cc index 985006e5a..6d7d928bd 100644 --- a/src/nix/optimise-store.cc +++ b/src/nix/optimise-store.cc @@ -1,5 +1,6 @@ #include "command.hh" #include "shared.hh" +#include "signals.hh" #include "store-api.hh" #include <atomic> diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 45cd2e1a6..730aa6532 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -2,6 +2,7 @@ #include "shared.hh" #include "store-api.hh" #include "thread-pool.hh" +#include "signals.hh" #include <atomic> diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 0b306cc11..9be4c25dc 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -3,6 +3,7 @@ #include "store-api.hh" #include "sync.hh" #include "thread-pool.hh" +#include "signals.hh" #include "references.hh" #include <atomic> |