1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-06 21:41:48 +02:00

Merge pull request #7732 from hercules-ci/make-initLibStore-viable-alternative

Make `initLibStore` a viable alternative
This commit is contained in:
John Ericson 2023-04-17 08:04:41 -04:00 committed by GitHub
commit 72ffa7fedb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 134 additions and 92 deletions

View file

@ -1,6 +1,7 @@
#include <iostream>
#include <cstring>
#include <openssl/crypto.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
@ -16,7 +17,6 @@
namespace nix {
static size_t regularHashSize(HashType type) {
switch (type) {
case htMD5: return md5HashSize;

View file

@ -47,6 +47,9 @@ extern char * * environ __attribute__((weak));
namespace nix {
void initLibUtil() {
}
std::optional<std::string> getEnv(const std::string & key)
{
char * value = getenv(key.c_str());
@ -1744,13 +1747,39 @@ void triggerInterrupt()
}
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();
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask))
throw SysError("querying signal mask");
saveSignalMask();
sigset_t set;
sigemptyset(&set);
@ -1767,6 +1796,20 @@ void startSignalHandlerThread()
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");
}

View file

@ -32,6 +32,7 @@ namespace nix {
struct Sink;
struct Source;
void initLibUtil();
/**
* The system for which Nix is compiled.
@ -445,6 +446,8 @@ void setStackSize(size_t stackSize);
/**
* Restore the original inherited Unix process context (such as signal
* masks, stack size).
* See startSignalHandlerThread(), saveSignalMask().
*/
void restoreProcessContext(bool restoreMounts = true);
@ -814,9 +817,26 @@ 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() { };