Author: enricopitea Date: To: devuan-dev Subject: [devuan-dev] [PATCH] runit: shutdown -h / poweroff does not cut the power — execv bypasses syscall_shutdown fallback
Hello Devuan developers,
I found a bug in runit's shutdown binary (debian/contrib/shutdown.c) that
affects Devuan systems using runit as PID 1.
== Symptom ==
On Devuan Ceres with runit, `shutdown -h now` and `poweroff` leave the system
in a state where services are stopped (stage 3 completes) but the hardware
never powers off. The kernel calls RB_HALT instead of RB_POWER_OFF. The user
must hold the power button to turn off the machine. The filesystem may show a
dirty bit on the next boot.
This was initially worked around on my machine by using `loginctl poweroff`,
but the root cause is in shutdown.distrib.
== Root Cause ==
In debian/contrib/shutdown.c (package runit 2.3.1-4), the function
runit_shutdown() at line 144 does:
is NEVER reached — the process no longer exists. PID 1 runs stage 3 and then
halts via RB_HALT, which stops the CPU but does not cut the power on modern
hardware.
Additionally, the flags -h, -P, and -H are all treated identically (the
source comment literally says "Halt actions not distinguished"), all mapping
to ACTION_HALT.
== Fix ==
Replace execv() with sysv_shutdown() — a function already present in the same
file (line 92) that writes to /run/initctl and RETURNS. The process survives,
sleep(15) runs, and syscall_shutdown(RB_POWER_OFF) is reached, correctly
powering off the hardware.
One function changed: -4 lines, +8 lines including the comment.
== Test Results ==
6 consecutive shutdowns on Devuan Ceres (kernel 7.1.5, runit 2.3.1-4):
- Realistic scenario: Firefox + Nemo + active NFS mount + 1.7 GB disk cache
- 6/6 clean: zero dirty bits, zero segfaults, BTRFS 0 corruption_errs
- Boot time: 93 seconds
The patch (shutdown.patch) is attached. It applies against runit 2.3.1-4,
file debian/contrib/shutdown.c.
== Notes ==
- The binary shutdown.distrib is shipped as a pre-compiled blob in
debian/contrib/ (not compiled during dpkg-buildpackage). The fix is in
the C source debian/contrib/shutdown.c.
- I am not submitting this to the Debian BTS directly because runit is a
first-class init system on Devuan and I believe the Devuan community
would review this more attentively. Feel free to forward it upstream if
appropriate.
Tested on: Devuan Ceres, i5-9600KF, 32 GB RAM, runit PID 1, Cinnamon desktop.
Date: 30 July 2026.
Disclosure: I used an AI assistant (DeepSeek V4 Pro) during the analysis. I
have personally reviewed the code and the patch to the best of my knowledge.