mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 13:33:09 +07:00
keventd: add -S settle mode polling /sys/kernel/uevent_seqnum
Stop-gap "settle" equivalent of udevadm settle for migration scenarios. Polls /sys/kernel/uevent_seqnum every 50ms and exits zero when the sequence number has been stable for 200ms (or non-zero after -t SECONDS timeout, default 30s). This is racy by design -- a slow probe firing after we return still races -- so the doc steers users toward dev/, class/, and bind/ conditions for any service they control. Settle is for legacy boot scripts and init transitions where condition wiring isn't feasible. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+23
-1
@@ -301,7 +301,7 @@ battery:
|
||||
Usage
|
||||
-----
|
||||
|
||||
keventd [-cdGhnpv] [-g GROUP] [-r DIR]
|
||||
keventd [-cdGhnpSv] [-g GROUP] [-r DIR] [-t SECONDS]
|
||||
|
||||
Options:
|
||||
-c Run coldplug at startup
|
||||
@@ -310,12 +310,34 @@ Usage
|
||||
-G Disable netlink rebroadcast entirely
|
||||
-h Show help text
|
||||
-n Run in foreground (no daemon)
|
||||
-p Passive mode: power supply events only
|
||||
-r DIR Extra rules directory
|
||||
-S Settle mode: wait for kernel uevent queue to quiet, then exit
|
||||
-t SEC Settle timeout (default 30s, used with -S)
|
||||
-v Show version
|
||||
|
||||
In normal operation, Finit starts keventd automatically via its system
|
||||
configuration. The `-d` flag is useful for debugging device issues --
|
||||
it runs keventd in the foreground and logs all received uevents.
|
||||
|
||||
`keventd -S` is a one-shot command, not a flag to the running daemon.
|
||||
It is the `udevadm settle` equivalent for migration scenarios:
|
||||
|
||||
keventd -S -t 10 && start-graphical-session
|
||||
|
||||
It does not talk to the running keventd (or any device manager) -- it
|
||||
simply opens `/sys/kernel/uevent_seqnum` and polls until the kernel's
|
||||
sequence counter has been stable for 200ms, then exits zero. After
|
||||
the `-t SECONDS` timeout (default 30) it exits non-zero instead.
|
||||
Because `uevent_seqnum` is maintained by the kernel itself, `-S` works
|
||||
regardless of which device manager is active, or even if none is.
|
||||
|
||||
Prefer the condition-based model (`<dev/X>`, `<class/...>`,
|
||||
`<driver/...>`) over settle when you control the service definition --
|
||||
settle is racy with slow probes that fire after the queue appears
|
||||
quiet. It is provided for legacy boot scripts and init transitions
|
||||
where condition wiring isn't feasible.
|
||||
|
||||
Debug logging can also be toggled at runtime by sending `SIGUSR1`:
|
||||
|
||||
kill -USR1 $(pidof keventd)
|
||||
|
||||
+63
-2
@@ -44,6 +44,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
@@ -536,10 +537,57 @@ static void uevent_cb(uev_t *w, void *arg, int events)
|
||||
rebc_event(rebc_buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop-gap "settle" mode: poll /sys/kernel/uevent_seqnum until it has
|
||||
* been stable for `stable_ms` (default 200ms), or until `timeout_s`
|
||||
* elapses. Imperfect -- a slow probe firing after we return still
|
||||
* races -- but matches what typical `udevadm settle` users want.
|
||||
*
|
||||
* The proper fix lives in the IPC/queue work (see audit doc).
|
||||
*/
|
||||
static int cmd_settle(int timeout_s, int stable_ms)
|
||||
{
|
||||
struct timespec start, last_change, now;
|
||||
unsigned long long last_seq = 0, cur_seq = 0;
|
||||
FILE *fp;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
last_change = start;
|
||||
|
||||
while (1) {
|
||||
fp = fopen("/sys/kernel/uevent_seqnum", "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "keventd: cannot read uevent_seqnum: %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (fscanf(fp, "%llu", &cur_seq) != 1)
|
||||
cur_seq = last_seq;
|
||||
fclose(fp);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
if (cur_seq != last_seq) {
|
||||
last_seq = cur_seq;
|
||||
last_change = now;
|
||||
} else {
|
||||
long dt_ms = (now.tv_sec - last_change.tv_sec) * 1000 +
|
||||
(now.tv_nsec - last_change.tv_nsec) / 1000000;
|
||||
if (dt_ms >= stable_ms)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (now.tv_sec - start.tv_sec >= timeout_s)
|
||||
return 1;
|
||||
|
||||
usleep(50000); /* 50ms */
|
||||
}
|
||||
}
|
||||
|
||||
static int usage(int rc)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: keventd [-dGhnpv] [-c] [-g GROUP] [-r DIR]\n"
|
||||
"Usage: keventd [-dGhnpSv] [-c] [-g GROUP] [-r DIR] [-t SECONDS]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -c Run coldplug at startup\n"
|
||||
@@ -550,6 +598,8 @@ static int usage(int rc)
|
||||
" -n Run in foreground (no daemon)\n"
|
||||
" -p Passive mode: power supply events only (no device management)\n"
|
||||
" -r DIR Extra rules directory (in addition to standard udev paths)\n"
|
||||
" -S Settle: wait until kernel uevent queue is quiet, then exit\n"
|
||||
" -t SEC Settle timeout in seconds (default: 30, with -S)\n"
|
||||
" -v Show version\n"
|
||||
"\n", REBC_DEFAULT_NLGROUP);
|
||||
|
||||
@@ -577,6 +627,8 @@ int main(int argc, char *argv[])
|
||||
uev_t netlink_watcher;
|
||||
uev_ctx_t ctx;
|
||||
int do_coldplug = 0;
|
||||
int do_settle = 0;
|
||||
int settle_timeout = 30;
|
||||
int foreground = 0;
|
||||
int nlfd;
|
||||
int c;
|
||||
@@ -586,7 +638,7 @@ int main(int argc, char *argv[])
|
||||
* requested bits verbatim instead of masking them. */
|
||||
umask(0);
|
||||
|
||||
while ((c = getopt(argc, argv, "cdg:Ghnpr:v")) != -1) {
|
||||
while ((c = getopt(argc, argv, "cdg:Ghnpr:St:v")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
do_coldplug = 1;
|
||||
@@ -612,6 +664,12 @@ int main(int argc, char *argv[])
|
||||
case 'r':
|
||||
rules_dir = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
do_settle = 1;
|
||||
break;
|
||||
case 't':
|
||||
settle_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
printf("keventd v%s\n", KEVENTD_VERSION);
|
||||
return 0;
|
||||
@@ -620,6 +678,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (do_settle)
|
||||
return cmd_settle(settle_timeout, 200);
|
||||
|
||||
if (!foreground) {
|
||||
openlog("keventd", LOG_PID, LOG_DAEMON);
|
||||
set_logging(LOG_NOTICE);
|
||||
|
||||
Reference in New Issue
Block a user