keventd: add passive mode (-p) for coexistence with hotplug plugin

This is a backwards compatible mode for users upgrading and not noticing
that keventd is now build by default.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-08-16 22:03:30 +02:00
parent 8e91bb4297
commit db5567b5d1
3 changed files with 54 additions and 32 deletions
+8 -6
View File
@@ -221,7 +221,7 @@ battery:
Usage
-----
keventd [-cdGhnv] [-g GROUP]
keventd [-cdGhnpv] [-g GROUP]
Options:
-c Run coldplug at startup
@@ -230,6 +230,7 @@ Usage
-G Disable netlink rebroadcast entirely
-h Show help text
-n Run in foreground (no daemon)
-p Passive mode: power supply events only
-v Show version
In normal operation, Finit starts keventd automatically via its system
@@ -259,11 +260,12 @@ This means keventd can also be tested independently:
# Run without rebroadcast (e.g., headless embedded system)
keventd -c -G
When keventd is enabled, it conflicts with external device managers.
Only one device manager should be active at a time. The system
configuration uses the `conflict:` directive to enforce this:
service conflict:udevd,mdevd,mdev [...] keventd -c -- Finit device manager
Only one device manager should be active at a time. This is settled
at build time: with the hotplug plugin enabled, Finit starts keventd
in passive mode (`-p`), leaving device management to the udevd, mdevd,
or mdev service from `system/10-hotplug.conf` and monitoring only
power supply events. Without the hotplug plugin, keventd runs as the
system device manager (`keventd -c`).
[libudev-zero]: https://github.com/illiliti/libudev-zero
[mdevd]: https://skarnet.org/software/mdevd/
+12 -4
View File
@@ -2683,15 +2683,23 @@ int conf_init(uev_ctx_t *ctx)
}
#endif
/*
* Start kernel event daemon as soon as possible, if enabled
* Start kernel event daemon as soon as possible, if enabled.
* In passive mode (-p) alongside the hotplug plugin, keventd
* only monitors power supply events (sys/pwr/ac condition).
*/
if (whichp(FINIT_EXECPATH_ "/keventd"))
conf_save_service(SVC_TYPE_SERVICE, "keventd", "keventd.conf",
"\tdescription = \"Finit kernel event daemon\"\n"
"\trunlevel = \"S12345789\"\n"
"\tdescription = \"kernel event daemon\"\n"
"\trunlevel = \"S0123456789\"\n"
"\tnotify = \"none\"\n"
"\tcgroup init {}\n"
"\tcommand = \"" FINIT_EXECPATH_ "/keventd\"\n");
"\tcommand = \"" FINIT_EXECPATH_ "/keventd"
#ifdef HAVE_HOTPLUG_PLUGIN
" -p"
#else
" -c"
#endif
"\"\n");
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
plugin_run_hooks(HOOK_SVC_PLUGIN);
+34 -22
View File
@@ -76,6 +76,7 @@ static int num_ac;
static int running = 1;
static int level;
static int logon;
static int passive; /* power-supply only, no device management */
int debug; /* debug in other modules as well */
@@ -283,29 +284,33 @@ static void handle_uevent(char *buf, size_t len)
switch (ev.action) {
case ACT_ADD:
/* Firmware loading takes priority */
if (ev.firmware)
firmware_load(&ev);
if (!passive) {
/* Firmware loading takes priority */
if (ev.firmware)
firmware_load(&ev);
/* Module loading */
if (ev.modalias)
modprobe_load(ev.modalias);
/* Module loading */
if (ev.modalias)
modprobe_load(ev.modalias);
/* Create device node if we have the info */
if (ev.major >= 0 && ev.minor >= 0 && ev.devname)
devnode_add(&ev);
/* Create device node if we have the info */
if (ev.major >= 0 && ev.minor >= 0 && ev.devname)
devnode_add(&ev);
/* Create symlinks */
symlink_add(&ev);
/* Create symlinks */
symlink_add(&ev);
}
break;
case ACT_REMOVE:
/* Remove symlinks first */
symlink_del(&ev);
if (!passive) {
/* Remove symlinks first */
symlink_del(&ev);
/* Remove device node */
if (ev.devname)
devnode_del(&ev);
/* Remove device node */
if (ev.devname)
devnode_del(&ev);
}
break;
case ACT_CHANGE:
@@ -412,7 +417,7 @@ static void shut_down(int signo)
static int usage(int rc)
{
fprintf(stderr,
"Usage: keventd [-dGhnv] [-c] [-g GROUP]\n"
"Usage: keventd [-dGhnpv] [-c] [-g GROUP]\n"
"\n"
"Options:\n"
" -c Run coldplug at startup\n"
@@ -421,6 +426,7 @@ static int usage(int rc)
" -G Disable netlink rebroadcast entirely\n"
" -h Show this help text\n"
" -n Run in foreground (no daemon)\n"
" -p Passive mode: power supply events only (no device management)\n"
" -v Show version\n"
"\n", REBC_DEFAULT_NLGROUP);
@@ -454,7 +460,7 @@ int main(int argc, char *argv[])
* requested bits verbatim instead of masking them. */
umask(0);
while ((c = getopt(argc, argv, "cdg:Ghnv")) != -1) {
while ((c = getopt(argc, argv, "cdg:Ghnpv")) != -1) {
switch (c) {
case 'c':
do_coldplug = 1;
@@ -474,6 +480,9 @@ int main(int argc, char *argv[])
case 'n':
foreground = 1;
break;
case 'p':
passive = 1;
break;
case 'v':
printf("keventd v%s\n", KEVENTD_VERSION);
return 0;
@@ -498,8 +507,10 @@ int main(int argc, char *argv[])
init_power_supply();
init_dev_condition_dir();
/* Disable legacy kernel uevent helper; we own events via netlink */
disable_uevent_helper();
/* Disable legacy kernel uevent helper; we own events via netlink.
* Skip in passive mode -- the hotplug daemon handles this. */
if (!passive)
disable_uevent_helper();
/* Set up netlink socket for kernel uevents */
pfd.events = POLLIN;
@@ -519,8 +530,9 @@ int main(int argc, char *argv[])
setsockopt(pfd.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
}
/* Initialize rebroadcast socket (default on, -G to disable) */
if (nlgroups)
/* Initialize rebroadcast socket (default on, -G to disable).
* Skip in passive mode -- the hotplug daemon rebroadcasts. */
if (nlgroups && !passive)
rebc_init(nlgroups);
/* Run coldplug if requested */