Compare commits

...
8 Commits
Author SHA1 Message Date
Joachim Wiberg 197c5767ea Switch from PTY to pipe for service log redirection
The PTY approach caused isatty() to return true for services using
the log directive, triggering programs like fprintd (using glib) to
emit ANSI escape codes and other TTY-specific formatting in syslog.

Using a standard pipe ensures isatty() correctly returns false, so
programs produce plain text output suitable for logging.

For services that require line-buffered output, users can wrap the
command with `stdbuf -oL` as documented in doc/config/logging.md.

Fixes #455

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-06 15:41:30 +01:00
Joachim Wiberg 22072e477c Change default reboot to SOC reset from WDT reset
Fixes #460

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-06 15:01:31 +01:00
Joachim Wiberg bda2f94e8a Allow skipping bootstrap wait with Ctrl-C
When setting up a new system with Finit it is very common to make small
logical mistakes that cause "hangs" at boot.  This is when Finit waits
for 180 sec. for run/tasks to complete before moving to the configured
runlevel.  This patch adds console input monitoring during bootstrap
wait that allows users to press Ctrl-C to skip waiting and proceed to
the configured runlevel.

When Ctrl-C is detected, all incomplete run/task/services are logged
to syslog for later troubleshooting after login.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-27 13:09:10 +01:00
Joachim Wiberg abb4561516 Allow more initctl commands in runlevels S/0/6
Relax the constraints introduced in a39ee0b, for issue #342, a bit on
when start/stop/restart/reload service can be called.  Also, allow
'initctl reload', but ignore it when the system is in runlevels S/0/6.

This makes it possible to start manual:yes type services at botostrap,
for example, which has been a common feature request.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-27 11:33:39 +01:00
Joachim Wiberg 309cc7f741 Ensure mount/unmount skips 'noauto' entries
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-27 11:30:27 +01:00
Joachim Wiberg c23952cd9e Merge pull request #453 from liuming50/fix-rtc-restore-issues
plugins:rtc.c: drop some invalid condition checks

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-10-14 20:33:25 +02:00
Ming Liu 13a8f56b46 plugins:rtc.c: drop some invalid condition checks
There are some invalid condition checks in rtc.c, when rtc_file is
missing, it should not consider that as a error and return, otherwise,
it can lead to the case that time_set wont be called at all.

With this fix, when both RTC and file restore fail, it will fall back
to call time_set(NULL) and restore time from rtc_timestamp, this
ensures the OS has a valid time at the very first boot.

Signed-off-by: Ming Liu <liu.ming50@gmail.com>
2025-10-14 15:38:56 +02:00
Joachim Wiberg 927acdbd7e Increase MAX_ID_LEN to support longer service identifiers
Allow service IDs up to 64 characters to support SHA-256 hashes,
UUIDs, and other long unique identifiers. This increases memory
usage by ~98 bytes per service instance, which is negligible for
typical deployments.

The IDENT column width in initctl output adapts dynamically based
on actual ID lengths in use, so short IDs remain unaffected.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-10-14 11:49:57 +02:00
13 changed files with 251 additions and 58 deletions
+22
View File
@@ -39,3 +39,25 @@ Log rotation is controlled using the global `log` setting.
**Example:** **Example:**
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
Output Buffering
----------------
When using the `log` directive, Finit redirects the service's stdout and
stderr to a pipe connected to a logger process. Programs detect this as
non-interactive output (i.e., `isatty()` returns false) and typically
switch from line-buffered to fully-buffered mode.
Most well-behaved daemons explicitly flush their output or use syslog
directly, so this is rarely an issue. However, if a service's log
messages appear delayed or batched, you can force line-buffered output
by wrapping the command with `stdbuf`:
service log /usr/bin/stdbuf -oL /path/to/command -- My service
The `-oL` option forces line-buffered output, and `-o0` forces unbuffered
output. See `stdbuf(1)` for details.
> [!NOTE]
> Using `stdbuf` is rarely necessary. Only use it if you observe actual
> buffering issues with a specific service.
+18
View File
@@ -166,3 +166,21 @@ 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
+21 -13
View File
@@ -170,16 +170,18 @@ static void file_save(void *arg)
static void file_restore(void *arg) static void file_restore(void *arg)
{ {
struct tm tm = { 0 }; struct tm tm = { 0 };
int rc = 1; int rc = 0;
FILE *fp; FILE *fp;
char msg[120];
if (!rtc_file) { if (!rtc_file) {
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore."); snprintf(msg, sizeof(msg), "Resetting system clock to kernel default, %s.", rtc_timestamp);
print_desc(NULL, msg);
rc = time_set(NULL);
print(rc, NULL);
return; return;
} }
print_desc(NULL, "Restoring system clock from backup");
fp = fopen(rtc_file, "r"); fp = fopen(rtc_file, "r");
if (fp) { if (fp) {
char buf[32]; char buf[32];
@@ -187,18 +189,25 @@ static void file_restore(void *arg)
if (fgets(buf, sizeof(buf), fp)) { if (fgets(buf, sizeof(buf), fp)) {
chomp(buf); chomp(buf);
strptime(buf, RTC_FMT, &tm); strptime(buf, RTC_FMT, &tm);
rc = time_set(&tm); if (!strptime(buf, RTC_FMT, &tm))
rc = 1;
} }
fclose(fp); fclose(fp);
} else }
logit(LOG_WARNING, "Missing %s", rtc_file); rc = 1;
if (rc) { if (rc) {
time_set(NULL); print_desc(NULL, "Failed to restore system clock from restore file");
rc = 2; print(2, NULL);
snprintf(msg, sizeof(msg), "Resetting system clock to kernel default, %s.", rtc_timestamp);
print_desc(NULL, msg);
rc = time_set(NULL);
print(rc, NULL);
} else {
print_desc(NULL, "Restoring system clock from restore file");
rc = time_set(&tm);
print(rc, NULL);
} }
print(rc, NULL);
} }
static int rtc_open(void) static int rtc_open(void)
@@ -292,8 +301,7 @@ static void rtc_restore(void *arg)
print(2, NULL); print(2, NULL);
/* Try restoring from last save game */ /* Try restoring from last save game */
if (rtc_file) file_restore(arg);
file_restore(arg);
} else } else
print(0, NULL); print(0, NULL);
+9 -8
View File
@@ -68,7 +68,8 @@ static int stop(svc_t *svc, void *user_data)
service_timeout_cancel(svc); service_timeout_cancel(svc);
svc_stop(svc); svc_stop(svc);
service_step(svc); service_step(svc);
service_step_all(SVC_TYPE_ANY); if (!IS_RESERVED_RUNLEVEL(runlevel))
service_step_all(SVC_TYPE_ANY);
return 0; return 0;
} }
@@ -83,7 +84,8 @@ static int start(svc_t *svc, void *user_data)
service_timeout_cancel(svc); service_timeout_cancel(svc);
svc_start(svc); svc_start(svc);
service_step(svc); service_step(svc);
service_step_all(SVC_TYPE_ANY); if (!IS_RESERVED_RUNLEVEL(runlevel))
service_step_all(SVC_TYPE_ANY);
return 0; return 0;
} }
@@ -391,11 +393,6 @@ static void api_cb(uev_t *w, void *arg, int events)
} }
switch (rq.cmd) { switch (rq.cmd) {
case INIT_CMD_RELOAD:
case INIT_CMD_START_SVC:
case INIT_CMD_RESTART_SVC:
case INIT_CMD_STOP_SVC:
case INIT_CMD_RELOAD_SVC:
case INIT_CMD_REBOOT: case INIT_CMD_REBOOT:
case INIT_CMD_HALT: case INIT_CMD_HALT:
case INIT_CMD_POWEROFF: case INIT_CMD_POWEROFF:
@@ -453,6 +450,10 @@ static void api_cb(uev_t *w, void *arg, int events)
break; break;
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */ case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
if (IS_RESERVED_RUNLEVEL(runlevel)) {
warnx("Ignoring reload in runlevel S and 6/0.");
goto done;
}
dbg("reload"); dbg("reload");
sm_reload(); sm_reload();
break; break;
@@ -576,7 +577,7 @@ static void api_cb(uev_t *w, void *arg, int events)
dbg("Unsupported cmd: %d", rq.cmd); dbg("Unsupported cmd: %d", rq.cmd);
break; break;
} }
done:
if (result) if (result)
rq.cmd = INIT_CMD_NACK; rq.cmd = INIT_CMD_NACK;
else else
+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;
+10
View File
@@ -212,6 +212,11 @@ static int fsck(int pass)
if (mnt->mnt_passno == 0 || mnt->mnt_passno != pass) if (mnt->mnt_passno == 0 || mnt->mnt_passno != pass)
continue; continue;
if (hasmntopt(mnt, "noauto")) {
dbg("Skipping fsck of %s, marked noauto", mnt->mnt_fsname);
continue;
}
/* Device to maybe fsck, */ /* Device to maybe fsck, */
dev = mnt->mnt_fsname; dev = mnt->mnt_fsname;
@@ -425,6 +430,11 @@ static void fs_swapon(char *cmd, size_t len)
if (strcmp(mnt->mnt_type, MNTTYPE_SWAP)) if (strcmp(mnt->mnt_type, MNTTYPE_SWAP))
continue; continue;
if (hasmntopt(mnt, "noauto")) {
dbg("Skipping swap %s, marked noauto", mnt->mnt_fsname);
continue;
}
snprintf(cmd, len, "swapon %s", mnt->mnt_fsname); snprintf(cmd, len, "swapon %s", mnt->mnt_fsname);
run_interactive(cmd, "Enabling swap %s", mnt->mnt_fsname); run_interactive(cmd, "Enabling swap %s", mnt->mnt_fsname);
} }
+51 -22
View File
@@ -271,25 +271,22 @@ static int lredirect(svc_t *svc)
{ {
static int have_sysklogd = -1; static int have_sysklogd = -1;
pid_t svc_pid = getpid(); pid_t svc_pid = getpid();
int pipefd[2];
pid_t pid; pid_t pid;
int fd; int fd;
/* /*
* Open PTY to connect to logger. A pty isn't buffered * Use a pipe to connect to logger. This ensures isatty()
* like a pipe, and it eats newlines so they aren't logged * returns false for the service, preventing programs from
* emitting ANSI escape codes and other TTY-specific output.
*/ */
fd = posix_openpt(O_RDWR); if (pipe(pipefd) == -1) {
if (fd == -1) { dbg("Failed pipe(), errno %d: %s", errno, strerror(errno));
dbg("Failed posix_openpt(), errno %d: %s", errno, strerror(errno));
svc->log.enabled = 0;
return -1;
}
if (grantpt(fd) == -1 || unlockpt(fd) == -1) {
dbg("Failed grantpt()|unlockpt(), errno %d: %s", errno, strerror(errno));
close(fd);
svc->log.enabled = 0; svc->log.enabled = 0;
return -1; return -1;
} }
fd = pipefd[1]; /* Write end for service */
/* /*
* First time, check if we have sysklogd logger tool. * First time, check if we have sysklogd logger tool.
@@ -319,17 +316,12 @@ static int lredirect(svc_t *svc)
char *prio = "daemon.info"; char *prio = "daemon.info";
char buf[MAX_IDENT_LEN]; char buf[MAX_IDENT_LEN];
char *tag; char *tag;
int fds;
sched_yield(); sched_yield();
fds = open(ptsname(fd), O_RDONLY); close(pipefd[1]); /* Close write end in logger */
close(fd); dup2(pipefd[0], STDIN_FILENO);
if (fds == -1) { close(pipefd[0]);
logit(LOG_WARNING, "failed open() ptsname(%d), errno %d", fd, errno);
_exit(0);
}
dup2(fds, STDIN_FILENO);
/* Reset signals */ /* Reset signals */
sig_unblock(); sig_unblock();
@@ -385,10 +377,11 @@ static int lredirect(svc_t *svc)
_exit(1); _exit(1);
} }
dup2(fd, STDOUT_FILENO); close(pipefd[0]); /* Close read end in service */
dup2(fd, STDERR_FILENO); dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);
return close(fd); return close(pipefd[1]);
} }
/* /*
@@ -3053,6 +3046,42 @@ int service_completed(svc_t **svcp)
return 1; return 1;
} }
/*
* service_log_incomplete - Log all incomplete run/task in current runlevel
*
* Iterates through all run/task services and logs those that have not
* yet completed. Useful for diagnosing bootstrap delays or reporting
* what was skipped when user interrupts bootstrap wait.
*/
void service_log_incomplete(void)
{
svc_t *svc, *iter = NULL;
int count = 0;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (!svc_is_runtask(svc))
continue;
if (!svc_enabled(svc))
continue;
if (svc_conflicts(svc))
continue;
if (strstr(svc->cond, plugin_hook_str(HOOK_SVC_UP)) ||
strstr(svc->cond, plugin_hook_str(HOOK_SYSTEM_UP)))
continue;
if (!svc->once) {
logit(LOG_WARNING, "Incomplete: %s", svc_ident(svc, NULL, 0));
count++;
}
}
if (count == 0)
logit(LOG_WARNING, "No incomplete run/task services found");
}
/* /*
* Called in SM_RELOAD_WAIT_STATE to update unmodified non-native * Called in SM_RELOAD_WAIT_STATE to update unmodified non-native
* services' READY condition to the current generation. Similar * services' READY condition to the current generation. Similar
+1
View File
@@ -48,6 +48,7 @@ void service_step_all (int types);
void service_worker (void *unused); void service_worker (void *unused);
int service_completed (svc_t **svc); int service_completed (svc_t **svc);
void service_log_incomplete (void);
void service_notify_reconf (void); void service_notify_reconf (void);
void service_init (uev_ctx_t *ctx); void service_init (uev_ctx_t *ctx);
+9 -4
View File
@@ -187,6 +187,11 @@ static void fs_swapoff(void)
if (strcmp(mnt->mnt_type, MNTTYPE_SWAP)) if (strcmp(mnt->mnt_type, MNTTYPE_SWAP))
continue; continue;
if (hasmntopt(mnt, "noauto")) {
dbg("Skipping swap %s, marked noauto", mnt->mnt_fsname);
continue;
}
snprintf(cmd, sizeof(cmd), "swapoff %s", mnt->mnt_fsname); snprintf(cmd, sizeof(cmd), "swapoff %s", mnt->mnt_fsname);
run_interactive(cmd, "Disabling swap %s", mnt->mnt_fsname); run_interactive(cmd, "Disabling swap %s", mnt->mnt_fsname);
} }
@@ -353,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);
} }
@@ -400,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 ...");
+87 -2
View File
@@ -23,8 +23,10 @@
#include "config.h" /* Generated by configure script */ #include "config.h" /* Generated by configure script */
#include <fcntl.h>
#include <paths.h> #include <paths.h>
#include <sys/types.h> #include <sys/types.h>
#include <termios.h>
#include "finit.h" #include "finit.h"
#include "cond.h" #include "cond.h"
@@ -56,8 +58,80 @@ static struct {
int newlevel; /* Set to new runlevel on change, -1 otherwise */ int newlevel; /* Set to new runlevel on change, -1 otherwise */
int reload; /* Set on reload event, else 0 */ int reload; /* Set on reload event, else 0 */
int in_reload; /* Set when waiting for all processes to be halted */ int in_reload; /* Set when waiting for all processes to be halted */
int skip_bootstrap; /* Set to skip bootstrap waiting */
} sm; } sm;
static uev_t console_watcher;
static int console_fd = -1;
/*
* Console input callback - handles Ctrl-C during bootstrap wait
*/
static void console_input_cb(uev_t *w, void *arg, int events)
{
ssize_t len;
char ch;
(void)arg;
if (UEV_ERROR == events) {
warnx("Error in console watcher");
return;
}
/* Read and check for Ctrl-C (ASCII 3) */
len = read(w->fd, &ch, 1);
if (len == 1 && ch == 3) { /* Ctrl-C */
sm.skip_bootstrap = 1;
print(2, "Bootstrap wait interrupted by Ctrl-C, resuming ...");
}
}
/*
* Stop and cleanup the console watcher
*/
static void console_watcher_stop(void)
{
if (console_fd >= 0) {
uev_io_stop(&console_watcher);
close(console_fd);
console_fd = -1;
}
}
/*
* Setup console watcher for Ctrl-C during bootstrap
*/
static void console_watcher_start(uev_ctx_t *ctx)
{
struct termios tio;
/* Open console in non-blocking mode */
console_fd = open(console(), O_RDONLY | O_NONBLOCK);
if (console_fd < 0) {
dbg("Failed opening console for input monitoring: %s", strerror(errno));
return;
}
/* Get current terminal settings */
if (tcgetattr(console_fd, &tio) == 0) {
/* Put terminal in raw mode to catch Ctrl-C */
tio.c_lflag &= ~(ICANON | ECHO | ISIG);
tio.c_cc[VMIN] = 0;
tio.c_cc[VTIME] = 0;
tcsetattr(console_fd, TCSANOW, &tio);
}
/* Register I/O watcher */
if (uev_io_init(ctx, &console_watcher, console_input_cb, NULL, console_fd, UEV_READ)) {
dbg("Failed setting up console watcher");
close(console_fd);
console_fd = -1;
} else {
dbg("Console watcher active, press Ctrl-C to skip bootstrap wait");
}
}
/* /*
* Wait for system bootstrap to complete, all SVC_TYPE_RUNTASK must be * Wait for system bootstrap to complete, all SVC_TYPE_RUNTASK must be
@@ -76,13 +150,19 @@ static void sm_check_bootstrap(void *work)
service_step_all(SVC_TYPE_ANY); service_step_all(SVC_TYPE_ANY);
bootstrap_done = service_completed(&svc); bootstrap_done = service_completed(&svc);
if (timeout-- > 0 && !bootstrap_done) { if (timeout-- > 0 && !bootstrap_done && !sm.skip_bootstrap) {
dbg("Not all bootstrap run/tasks have completed yet ... %d", timeout); dbg("Not all bootstrap run/tasks have completed yet ... %d", timeout);
schedule_work(work); schedule_work(work);
return; return;
} }
if (timeout > 0) { /* Stop console watcher before proceeding */
console_watcher_stop();
if (sm.skip_bootstrap) {
logit(LOG_WARNING, "Ctrl-C received, skipped waiting for the following:");
service_log_incomplete();
} else if (timeout > 0) {
dbg("All run/task have completed, resuming bootstrap."); dbg("All run/task have completed, resuming bootstrap.");
} else { } else {
dbg("Timeout, resuming bootstrap."); dbg("Timeout, resuming bootstrap.");
@@ -184,6 +264,7 @@ void sm_init(void)
sm.newlevel = -1; sm.newlevel = -1;
sm.reload = 0; sm.reload = 0;
sm.in_reload = 0; sm.in_reload = 0;
sm.skip_bootstrap = 0;
dbg("Starting bootstrap finalize timer ..."); dbg("Starting bootstrap finalize timer ...");
schedule_work(&work); schedule_work(&work);
@@ -206,6 +287,7 @@ restart:
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE | SVC_TYPE_SYSV); service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE | SVC_TYPE_SYSV);
sm.state = SM_BOOTSTRAP_WAIT_STATE; sm.state = SM_BOOTSTRAP_WAIT_STATE;
console_watcher_start(ctx);
break; break;
/* /*
@@ -229,6 +311,9 @@ restart:
if (sm.newlevel == -1) if (sm.newlevel == -1)
break; break;
/* Ensure console watcher is stopped before proceeding */
console_watcher_stop();
/* Hooks that should run at the very end */ /* Hooks that should run at the very end */
dbg("Calling all system up hooks ..."); dbg("Calling all system up hooks ...");
plugin_run_hooks(HOOK_SYSTEM_UP); plugin_run_hooks(HOOK_SYSTEM_UP);
+1 -1
View File
@@ -94,7 +94,7 @@ typedef enum {
SVC_NOTIFY_S6, SVC_NOTIFY_S6,
} svc_notify_t; } svc_notify_t;
#define MAX_ID_LEN 16 #define MAX_ID_LEN 65
#define MAX_ARG_LEN 64 #define MAX_ARG_LEN 64
#define MAX_CMD_LEN 256 #define MAX_CMD_LEN 256
#define MAX_IDENT_LEN (MAX_ARG_LEN + MAX_ID_LEN + 1) #define MAX_IDENT_LEN (MAX_ARG_LEN + MAX_ID_LEN + 1)