From 2473e1253d37d4bbd3f7aad2ff269ad84747d527 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Tue, 28 May 2024 13:36:02 +0200 Subject: util.{hh,cc}: Split out current-process.{hh,cc} Change-Id: I77095b9d37e85310075bada7a076ccd482c28e47 --- src/libutil/current-process.cc | 109 +++++++++++++++++++++++++++++++++++++++++ src/libutil/current-process.hh | 37 ++++++++++++++ src/libutil/meson.build | 2 + src/libutil/processes.cc | 1 + src/libutil/util.cc | 87 +------------------------------- src/libutil/util.hh | 26 ---------- 6 files changed, 150 insertions(+), 112 deletions(-) create mode 100644 src/libutil/current-process.cc create mode 100644 src/libutil/current-process.hh (limited to 'src/libutil') diff --git a/src/libutil/current-process.cc b/src/libutil/current-process.cc new file mode 100644 index 000000000..826e25547 --- /dev/null +++ b/src/libutil/current-process.cc @@ -0,0 +1,109 @@ +#include "current-process.hh" +#include "file-system.hh" +#include "logging.hh" +#include "signals.hh" +#include "util.hh" + +#ifdef __APPLE__ +# include +#endif + +#if __linux__ +# include +#endif + +#include +#include + +namespace nix { + +unsigned int getMaxCPU() +{ + #if __linux__ + try { + auto cgroupFS = getCgroupFS(); + if (!cgroupFS) return 0; + + auto cgroups = getCgroups("/proc/self/cgroup"); + auto cgroup = cgroups[""]; + if (cgroup == "") return 0; + + auto cpuFile = *cgroupFS + "/" + cgroup + "/cpu.max"; + + auto cpuMax = readFile(cpuFile); + auto cpuMaxParts = tokenizeString>(cpuMax, " \n"); + + if (cpuMaxParts.size() != 2) { + return 0; + } + + auto quota = cpuMaxParts[0]; + auto period = cpuMaxParts[1]; + if (quota != "max") + return std::ceil(std::stoi(quota) / std::stof(period)); + } catch (Error &) { ignoreException(lvlDebug); } + #endif + + return 0; +} + +rlim_t savedStackSize = 0; + +void setStackSize(rlim_t stackSize) +{ + struct rlimit limit; + if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) { + savedStackSize = limit.rlim_cur; + limit.rlim_cur = std::min(stackSize, limit.rlim_max); + if (setrlimit(RLIMIT_STACK, &limit) != 0) { + logger->log( + lvlError, + HintFmt( + "Failed to increase stack size from %1% to %2% (maximum allowed stack size: %3%): %4%", + savedStackSize, + stackSize, + limit.rlim_max, + std::strerror(errno) + ).str() + ); + } + } +} + +void restoreProcessContext(bool restoreMounts) +{ + restoreSignals(); + if (restoreMounts) { + restoreMountNamespace(); + } + + if (savedStackSize) { + struct rlimit limit; + if (getrlimit(RLIMIT_STACK, &limit) == 0) { + limit.rlim_cur = savedStackSize; + setrlimit(RLIMIT_STACK, &limit); + } + } +} + +std::optional getSelfExe() +{ + static auto cached = []() -> std::optional + { + #if __linux__ + return readLink("/proc/self/exe"); + #elif __APPLE__ + char buf[1024]; + uint32_t size = sizeof(buf); + if (_NSGetExecutablePath(buf, &size) == 0) + return buf; + else + return std::nullopt; + #else + return std::nullopt; + #endif + }(); + return cached; +} + +} diff --git a/src/libutil/current-process.hh b/src/libutil/current-process.hh new file mode 100644 index 000000000..8d5a2791d --- /dev/null +++ b/src/libutil/current-process.hh @@ -0,0 +1,37 @@ +#pragma once +///@file + +#include +#include + +#include "types.hh" + +namespace nix { + +/** + * If cgroups are active, attempt to calculate the number of CPUs available. + * If cgroups are unavailable or if cpu.max is set to "max", return 0. + */ +unsigned int getMaxCPU(); + + +/** + * Change the stack size. + */ +void setStackSize(rlim_t stackSize); + + +/** + * Restore the original inherited Unix process context (such as signal + * masks, stack size). + + * See startSignalHandlerThread(), saveSignalMask(). + */ +void restoreProcessContext(bool restoreMounts = true); + +/** + * @return the path of the current executable. + */ +std::optional getSelfExe(); + +} diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 34715b25e..ef4270066 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -6,6 +6,7 @@ libutil_sources = files( 'compression.cc', 'compute-levels.cc', 'config.cc', + 'current-process.cc', 'english.cc', 'environment-variables.cc', 'error.cc', @@ -56,6 +57,7 @@ libutil_headers = files( 'compute-levels.hh', 'config-impl.hh', 'config.hh', + 'current-process.hh', 'english.hh', 'environment-variables.hh', 'error.hh', diff --git a/src/libutil/processes.cc b/src/libutil/processes.cc index 8d1b119b0..8639a77f8 100644 --- a/src/libutil/processes.cc +++ b/src/libutil/processes.cc @@ -1,3 +1,4 @@ +#include "current-process.hh" #include "environment-variables.hh" #include "finally.hh" #include "logging.hh" diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 702db2afb..7f9413f8d 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1,5 +1,6 @@ #include "util.hh" #include "processes.hh" +#include "current-process.hh" #include "sync.hh" #include "finally.hh" @@ -148,59 +149,11 @@ Path createNixStateDir() } -std::optional getSelfExe() -{ - static auto cached = []() -> std::optional - { - #if __linux__ - return readLink("/proc/self/exe"); - #elif __APPLE__ - char buf[1024]; - uint32_t size = sizeof(buf); - if (_NSGetExecutablePath(buf, &size) == 0) - return buf; - else - return std::nullopt; - #else - return std::nullopt; - #endif - }(); - return cached; -} ////////////////////////////////////////////////////////////////////// -unsigned int getMaxCPU() -{ - #if __linux__ - try { - auto cgroupFS = getCgroupFS(); - if (!cgroupFS) return 0; - - auto cgroups = getCgroups("/proc/self/cgroup"); - auto cgroup = cgroups[""]; - if (cgroup == "") return 0; - - auto cpuFile = *cgroupFS + "/" + cgroup + "/cpu.max"; - - auto cpuMax = readFile(cpuFile); - auto cpuMaxParts = tokenizeString>(cpuMax, " \n"); - - if (cpuMaxParts.size() != 2) { - return 0; - } - - auto quota = cpuMaxParts[0]; - auto period = cpuMaxParts[1]; - if (quota != "max") - return std::ceil(std::stoi(quota) / std::stof(period)); - } catch (Error &) { ignoreException(lvlDebug); } - #endif - - return 0; -} ////////////////////////////////////////////////////////////////////// @@ -454,28 +407,6 @@ std::pair getLine(std::string_view s) ////////////////////////////////////////////////////////////////////// -rlim_t savedStackSize = 0; - -void setStackSize(rlim_t stackSize) -{ - struct rlimit limit; - if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) { - savedStackSize = limit.rlim_cur; - limit.rlim_cur = std::min(stackSize, limit.rlim_max); - if (setrlimit(RLIMIT_STACK, &limit) != 0) { - logger->log( - lvlError, - HintFmt( - "Failed to increase stack size from %1% to %2% (maximum allowed stack size: %3%): %4%", - savedStackSize, - stackSize, - limit.rlim_max, - std::strerror(errno) - ).str() - ); - } - } -} #if __linux__ static AutoCloseFD fdSavedMountNamespace; @@ -528,22 +459,6 @@ void unshareFilesystem() #endif } -void restoreProcessContext(bool restoreMounts) -{ - restoreSignals(); - if (restoreMounts) { - restoreMountNamespace(); - } - - if (savedStackSize) { - struct rlimit limit; - if (getrlimit(RLIMIT_STACK, &limit) == 0) { - limit.rlim_cur = savedStackSize; - setrlimit(RLIMIT_STACK, &limit); - } - } -} - AutoCloseFD createUnixDomainSocket() { AutoCloseFD fdSocket{socket(PF_UNIX, SOCK_STREAM diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 8d1900131..de5f0a2ee 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -71,11 +71,6 @@ std::vector getConfigDirs(); */ Path getDataDir(); -/** - * @return the path of the current executable. - */ -std::optional getSelfExe(); - /** * @return $XDG_STATE_HOME or $HOME/.local/state. * @@ -91,27 +86,6 @@ Path getStateDir(); Path createNixStateDir(); -/** - * If cgroups are active, attempt to calculate the number of CPUs available. - * If cgroups are unavailable or if cpu.max is set to "max", return 0. - */ -unsigned int getMaxCPU(); - - -/** - * Change the stack size. - */ -void setStackSize(rlim_t stackSize); - - -/** - * Restore the original inherited Unix process context (such as signal - * masks, stack size). - - * See startSignalHandlerThread(), saveSignalMask(). - */ -void restoreProcessContext(bool restoreMounts = true); - /** * Save the current mount namespace. Ignored if called more than * once. -- cgit v1.2.3