Install this version:
emerge -a =sys-process/nohang-9999
If this version is masked, you can unmask it using the autounmask tool or standard emerge options:
autounmask =sys-process/nohang-9999
Or alternatively:
emerge --autounmask-write -a =sys-process/nohang-9999
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
PYTHON_COMPAT=( python3_{12..15} )
inherit python-single-r1 systemd
DESCRIPTION="Low memory handler that acts on PSI pressure before the kernel OOM killer"
HOMEPAGE="https://github.com/hakavlad/nohang"
if [[ ${PV} == 9999 ]]; then
inherit git-r3
EGIT_REPO_URI="https://github.com/hakavlad/nohang.git"
else
SRC_URI="https://github.com/hakavlad/nohang/archive/v${PV}.tar.gz -> ${P}.tar.gz"
KEYWORDS="~amd64 ~arm64 ~x86"
fi
LICENSE="MIT"
SLOT="0"
IUSE="desktop systemd"
REQUIRED_USE="${PYTHON_REQUIRED_USE}"
# The daemon itself is pure stdlib Python. The desktop profile shells out to
# notify-send through sudo to reach the logged-in user's session bus.
RDEPEND="
${PYTHON_DEPS}
desktop? (
app-admin/sudo
x11-libs/libnotify
)
"
src_prepare() {
default
# The Makefile takes the version string from `git describe`, which leaves
# the file empty when building from a release tarball: the shell truncates
# it before git fails, and the `-` prefix swallows the error.
sed -i \
-e "s|-git describe --tags --long --dirty > version|echo v${PV} > version|" \
Makefile || die "failed to pin the version string"
# The Makefile gzips the manpages on its way into ${D}. Portage compresses
# man/ itself, and warns about anything that arrives already compressed, so
# hand the pages over as-is and let docompress decide.
sed -i \
-e 's|gzip -9cn \(\S*\) > \(\S*\)\.gz|install -p -m0644 \1 \2|' \
Makefile || die "failed to defer manpage compression to portage"
if grep -q 'gzip -9cn' Makefile; then
die "manpage gzip calls left in the Makefile"
fi
# /var/run is a compat symlink; OpenRC pidfiles belong in /run, and want
# the .pid suffix that start-stop-daemon consumers expect.
sed -i \
-e 's|pidfile="/var/run/nohang"|pidfile="/run/nohang.pid"|' \
openrc/nohang.in || die "failed to relocate the nohang pidfile"
sed -i \
-e 's|pidfile="/var/run/nohang-desktop"|pidfile="/run/nohang-desktop.pid"|' \
openrc/nohang-desktop.in || die "failed to relocate the nohang-desktop pidfile"
}
src_compile() {
# Nothing to build: every executable is a standalone Python script, and the
# manpages ship pregenerated. The upstream `all` target only prints a hint.
:
}
src_install() {
local makeargs=(
DESTDIR="${D}"
PREFIX="${EPREFIX}/usr"
SYSCONFDIR="${EPREFIX}/etc"
DOCDIR="${EPREFIX}/usr/share/doc/${PF}"
)
# The daemon, the two config profiles, the manpages and the logrotate
# snippet. Everything init-system specific is handled below.
emake "${makeargs[@]}" base
# The init scripts are deliberately NOT gated on USE=systemd: they cost a
# systemd user nothing, and they are the only way to start the daemon on a
# host that does not run systemd.
#
# Expanded here rather than through the upstream install-openrc target,
# which installs them 0775 - group-writable, for scripts that run as root.
local svc
for svc in nohang nohang-desktop; do
sed \
-e "s|:TARGET_SBINDIR:|${EPREFIX}/usr/sbin|" \
-e "s|:TARGET_SYSCONFDIR:|${EPREFIX}/etc|" \
"openrc/${svc}.in" > "${T}/${svc}.initd" || die "failed to expand the ${svc} init script"
newinitd "${T}/${svc}.initd" "${svc}"
done
# `units` is invoked on its own rather than through the upstream `install`
# target, which also runs chcon and `systemctl daemon-reload` against the
# live host instead of against ${D}.
if use systemd; then
emake "${makeargs[@]}" \
SYSTEMDUNITDIR="$(systemd_get_systemunitdir)" units
fi
python_fix_shebang "${ED}"
# Referenced by the shipped logrotate snippet and by separate_log = True.
keepdir /var/log/nohang
}
pkg_postinst() {
if [[ -z ${REPLACING_VERSIONS} ]]; then
elog "Two profiles are installed, and they conflict - enable only one:"
elog " nohang - conservative, headless-safe defaults"
elog " nohang-desktop - tuned for interactive use, sends GUI warnings"
elog
elog "OpenRC: rc-update add nohang default && rc-service nohang start"
if use systemd; then
elog "systemd: systemctl enable --now nohang.service"
fi
elog
elog "GUI notifications from the desktop profile need USE=desktop."
if [[ ! -e /proc/pressure/memory ]]; then
elog
elog "This kernel exposes no /proc/pressure/memory: PSI is off."
elog "Enable CONFIG_PSI, and boot with psi=1 if CONFIG_PSI_DEFAULT_DISABLED"
elog "is set. Without PSI, nohang falls back to plain memory thresholds."
fi
fi
}
Manage flags for this package:
euse -i <flag> -p sys-process/nohang |
euse -E <flag> -p sys-process/nohang |
euse -D <flag> -p sys-process/nohang