Change default reboot to SOC reset from WDT reset

Fixes #460

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2025-12-07 09:38:13 +01:00
1 parent 4e18affa9b
commit 178301baf2
5 files changed
+44 -12

No files matched your search

+19 -1
View File
@@ -165,4 +165,22 @@ sync(2) has been called, twice.
> "On Linux, sync is only guaranteed to schedule the dirty blocks for > "On Linux, sync is only guaranteed to schedule the dirty blocks for
> writing; it can actually take a short time before all the blocks are > writing; it can actually take a short time before all the blocks are
> finally written. > finally written.
**Syntax:** `reboot-watchdog <on|off|true|false|1|0>`
Controls whether the system should reboot via the watchdog timer (WDT)
or directly via the SoC/kernel. When enabled, Finit will:
1. Send `SIGPWR` to the registered watchdog daemon before shutdown
2. Send `SIGTERM` to the watchdog daemon and wait up to 10 seconds
for the watchdog to trigger a hardware reset
When disabled (default), Finit skips the watchdog reboot logic and
calls the kernel's `reboot(2)` syscall directly for a clean SoC reboot.
*Default:* off (reboot via SoC)
> [!NOTE]
> This setting only affects reboots. The watchdog daemon will still
> run and monitor the system during normal operation.
+14 -7
View File
@@ -10,14 +10,21 @@ many embedded systems this is crucial to ensure all circuits on the
board are properly reset for the next boot, in effect ensuring the board are properly reset for the next boot, in effect ensuring the
system works the same after both a power-on and reboot event. system works the same after both a power-on and reboot event.
> [!NOTE]
> The watchdog reboot delegation can be enabled with the `reboot-watchdog`
> configuration option in `/etc/finit.conf`. By default this is disabled
> and the system reboots directly via the SoC using the kernel's `reboot(2)`
> syscall. See [Runlevels](config/runlevels.md) for details.
The delegation is performed at the very last steps of system shutdown, The delegation is performed at the very last steps of system shutdown,
if reboot has been selected and an elected watchdog is known, first a if reboot has been selected, `reboot-watchdog` is enabled, and an elected
`SIGPWR` is sent to advise watchdogd of the pending reboot. Then, when watchdog is known. First a `SIGPWR` is sent to advise watchdogd of the
the necessary steps of preparing the system for shutdown (umount etc.) pending reboot. Then, when the necessary steps of preparing the system
are completed, Finit sends `SIGTERM` to watchdogd and puts itself in a for shutdown (umount etc.) are completed, Finit sends `SIGTERM` to
10 sec timeout loop waiting for the WDT to reset the board. If a reset watchdogd and puts itself in a 10 sec timeout loop waiting for the WDT
is not done before the timeout, Finit falls back to`reboot(RB_AUTOBOOT)` to reset the board. If a reset is not done before the timeout, Finit
which tells the kernel to do the reboot. falls back to `reboot(RB_AUTOBOOT)` which tells the kernel to do the
reboot.
An external watchdog service can also be used. The more advanced cousin An external watchdog service can also be used. The more advanced cousin
[watchdogd](https://github.com/troglobit/watchdogd/) is the recommended [watchdogd](https://github.com/troglobit/watchdogd/) is the recommended
+6
View File
@@ -60,6 +60,7 @@ int single = 0; /* single user mode from kernel cmdline */
int bootstrap = 1; /* set while bootstrapping (for TTYs) */ int bootstrap = 1; /* set while bootstrapping (for TTYs) */
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */ int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
int syncsec = 0; /* reboot delay */ int syncsec = 0; /* reboot delay */
int wdtreboot = 0; /* reboot via watchdog, default: SOC */
int readiness = SVC_NOTIFY_PID; int readiness = SVC_NOTIFY_PID;
char *finit_conf= NULL; char *finit_conf= NULL;
char *finit_rcsd= NULL; char *finit_rcsd= NULL;
@@ -1034,6 +1035,11 @@ static int parse_static(char *line, int is_rcsd)
return 0; return 0;
} }
if (MATCH_CMD(line, "reboot-watchdog ", x)) {
wdtreboot = get_bool(strip_line(x), 0);
return 0;
}
/* /*
* Periodic check and instability index leveler, seconds * Periodic check and instability index leveler, seconds
*/ */
+1
View File
@@ -37,6 +37,7 @@ extern int single;
extern int bootstrap; extern int bootstrap;
extern int kerndebug; extern int kerndebug;
extern int syncsec; extern int syncsec;
extern int wdtreboot;
extern int readiness; extern int readiness;
extern char *fstab; extern char *fstab;
extern char *sdown; extern char *sdown;
+4 -4
View File
@@ -358,7 +358,7 @@ void do_shutdown(shutop_t op)
return; return;
} }
if (wdog) { if (wdtreboot && wdog) {
print(kill(wdog->pid, SIGPWR) == 1, "Advising watchdog, system going down"); print(kill(wdog->pid, SIGPWR) == 1, "Advising watchdog, system going down");
do_sleep(2); do_sleep(2);
} }
@@ -405,17 +405,17 @@ void do_shutdown(shutop_t op)
/* Reboot via watchdog or kernel, or shutdown? */ /* Reboot via watchdog or kernel, or shutdown? */
if (op == SHUT_REBOOT) { if (op == SHUT_REBOOT) {
print(0, "Rebooting ..."); if (wdtreboot && wdog && wdog->pid > 1) {
if (wdog && wdog->pid > 1) {
int timeout = 10; int timeout = 10;
/* Wait here until the WDT reboots, or timeout with fallback */ /* Wait here until the WDT reboots, or timeout with fallback */
print(0, "Rebooting using WDT, please wait ...");
print(kill(wdog->pid, SIGTERM) == 1, "Pending watchdog reboot"); print(kill(wdog->pid, SIGTERM) == 1, "Pending watchdog reboot");
while (timeout--) while (timeout--)
do_sleep(1); do_sleep(1);
} }
dbg("Rebooting ..."); print(0, "Rebooting ...");
reboot(RB_AUTOBOOT); reboot(RB_AUTOBOOT);
} else if (op == SHUT_OFF) { } else if (op == SHUT_OFF) {
print(0, "Powering down ..."); print(0, "Powering down ...");