Merge pull request #1087 from kernelkit/cleanup

This commit is contained in:
Joachim Wiberg
2025-08-11 17:33:38 +02:00
committed by GitHub
18 changed files with 6 additions and 569 deletions
-1
View File
@@ -10,7 +10,6 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/confd-test-mode/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-httpd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-nftables/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/execd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/gencert/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/statd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in"
-8
View File
@@ -1,8 +0,0 @@
config BR2_PACKAGE_EXECD
bool "execd"
select BR2_PACKAGE_LIBUEV
select BR2_PACKAGE_LIBITE
help
Generic job queue executor with retry on route changes.
https://github.com/kernelkit/infix
-4
View File
@@ -1,4 +0,0 @@
task log:prio:local1.notice,tag:container-flush <pid/syslogd> \
[S] container flush -- Cleaning up lingering containers
service log:prio:local1.err,tag:container \
[2345] execd /run/containers/queue -- Container job runner
-1
View File
@@ -1 +0,0 @@
sha256 fff5e150e496c6bb6035ae388ee13cf2d0df842335e5145a4b902ef6b7892088 LICENSE
-29
View File
@@ -1,29 +0,0 @@
################################################################################
#
# execd
#
################################################################################
EXECD_VERSION = 1.0
EXECD_SITE_METHOD = local
EXECD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/execd
EXECD_LICENSE = ISC
EXECD_LICENSE_FILES = LICENSE
EXECD_REDISTRIBUTE = NO
EXECD_DEPENDENCIES = libuev libite
EXECD_AUTORECONF = YES
define EXECD_CONF_ENV
CFLAGS="$(INFIX_CFLAGS)"
endef
EXECD_CONF_OPTS = --prefix= --disable-silent-rules
define EXECD_INSTALL_EXTRA
cp $(EXECD_PKGDIR)/execd.conf $(FINIT_D)/available/
ln -sf ../available/execd.conf $(FINIT_D)/enabled/execd.conf
cp $(EXECD_PKGDIR)/tmpfiles.conf $(TARGET_DIR)/lib/tmpfiles.d/execd.conf
endef
EXECD_TARGET_FINALIZE_HOOKS += EXECD_INSTALL_EXTRA
$(eval $(autotools-package))
-1
View File
@@ -1 +0,0 @@
d /run/containers/queue 0700 - -
+1 -1
View File
@@ -1,5 +1,5 @@
# Host build of critical components, for Coverity Scan mostly
APPS = bin confd execd factory keyack statd
APPS = bin confd factory keyack statd
.PHONY: all
all:
-4
View File
@@ -26,10 +26,6 @@ static int do_erase(const char *path)
}
cfg_adjust(path, NULL, fn, len);
if (access(fn, F_OK)) {
fprintf(stderr, "No such file: %s\n", fn);
return -1;
}
} else
fn = (char *)path;
+5 -2
View File
@@ -14,7 +14,7 @@
static char rawgetch(void)
{
struct termios saved, c;
char key;
int key;
if (tcgetattr(fileno(stdin), &saved) < 0)
return -1;
@@ -33,7 +33,10 @@ static char rawgetch(void)
key = getchar();
tcsetattr(fileno(stdin), TCSANOW, &saved);
return key;
if (key == EOF)
return -1;
return (char)key;
}
int yorn(const char *fmt, ...)
-28
View File
@@ -1,28 +0,0 @@
*~
*.o
execd
/aclocal.m4
/autom4te.cache/
/aux
/clixon.xml
/compile
/config.h
/config.h.in
/config.guess
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4
/missing
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
-14
View File
@@ -1,14 +0,0 @@
Copyright (c) 2024 The KernelKit Authors
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
-9
View File
@@ -1,9 +0,0 @@
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
sbin_PROGRAMS = execd
execd_SOURCES = execd.c execd.h
execd_CPPFLAGS = -D_GNU_SOURCE
execd_CFLAGS = -W -Wall -Wextra -Wno-unused
execd_CFLAGS = $(libuev_CFLAGS) $(libite_CFLAGS)
execd_LDADD = $(libuev_LIBS) $(libite_LIBS)
-9
View File
@@ -1,9 +0,0 @@
Execute jobs on route changes
=============================
This is a generic job queue executor for work that needs network access.
For example creating a Docker container by downloading an image from the
network -- if the download fails `execd` retries the job whenever there
is a route change.
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
autoreconf -W portability -vifm
-5
View File
@@ -1,5 +0,0 @@
all:
./autogen.sh
./configure
make all
make distclean
-65
View File
@@ -1,65 +0,0 @@
AC_PREREQ(2.61)
AC_INIT([execd], [1.0.0], [https://github.com/kernelkit/infix/issues])
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
AM_SILENT_RULES(yes)
AC_CONFIG_FILES([
Makefile
])
AC_PROG_CC
AC_PROG_INSTALL
# Check for pkg-config first, warn if it's not installed
PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([libuev], [libuev >= 2.4.0])
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
test "x$prefix" = xNONE && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DATAROOTDIR=`eval echo $datarootdir`
DATAROOTDIR=`eval echo $DATAROOTDIR`
AC_SUBST(DATAROOTDIR)
LIBDIR=`eval echo $libdir`
LIBDIR=`eval echo $LIBDIR`
AC_SUBST(LIBDIR)
LOCALSTATEDIR=`eval echo $localstatedir`
LOCALSTATEDIR=`eval echo $LOCALSTATEDIR`
AC_SUBST(LOCALSTATEDIR)
RUNSTATEDIR=`eval echo $runstatedir`
RUNSTATEDIR=`eval echo $RUNSTATEDIR`
AC_SUBST(RUNSTATEDIR)
SYSCONFDIR=`eval echo $sysconfdir`
SYSCONFDIR=`eval echo $SYSCONFDIR`
AC_SUBST(SYSCONFDIR)
AC_OUTPUT
cat <<EOF
------------------ Summary ------------------
$PACKAGE_NAME version $PACKAGE_VERSION
Prefix................: $prefix
Exec prefix...........: $eprefix
Sysconfdir............: `eval echo $sysconfdir`
Localstatedir.........: `eval echo $localstatedir`
System environment....: ${sysconfig_path:-${sysconfig}}
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
------------- Compiler version --------------
$($CC --version || true)
-------------- Linker version ---------------
$($LD --version || true)
---------------------------------------------
Check the above options and compile with:
${MAKE-make}
EOF
-309
View File
@@ -1,309 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include "execd.h"
#define RETRY_TIMER 60
static uev_t retry_watcher;
static int retry = RETRY_TIMER;
static int logmask = LOG_UPTO(LOG_NOTICE);
static char buffer[BUFSIZ];
static int run_job(const char *path, const char *file)
{
char cmd[strlen(path) + strlen(file) + 2];
int rc;
/*
* Unfortunately, on some systems (x86_64), execd reacts too
* quickly to route and inotify events. So we have this load
* bearing sleep here to guard against "text file busy" and
* "destination unreachable" errors.
*/
usleep(500000);
snprintf(cmd, sizeof(cmd), "%s/%s", path, file);
if (access(cmd, X_OK)) {
errx("%s skipping, not executable.", cmd);
return -1;
}
dbg("running job %s", cmd);
if ((rc = systemf("%s", cmd))) {
errx("%s failed, exit code: %d", cmd, rc);
return -1;
}
return erase(cmd);
}
static int run_dir(const char *path, int type)
{
struct dirent **namelist;
int n, i, num = 0;
n = scandir(path, &namelist, NULL, alphasort);
if (n < 0) {
err("scandir %s", path);
return 0;
}
for (i = 0; i < n; i++) {
struct dirent *d = namelist[i];
if (d->d_type == DT_DIR)
continue;
if (should_run(d->d_name, type))
num += !!run_job(path, d->d_name);
free(d);
}
free(namelist);
return num;
}
/*
* Call stop/cleanup jobs first, may use same container name or
* resources as replacement container start scripts use.
*/
static void run_queue(const char *path)
{
int num;
num = run_dir(path, 'K');
num += run_dir(path, 'S');
if (num)
uev_timer_set(&retry_watcher, retry, 0);
}
static void signal_cb(uev_t *w, void *arg, int signo)
{
dbg("signal %d, calling job queue", signo);
run_queue(arg);
}
static void timer_cb(uev_t *w, void *arg, int _)
{
dbg("timer, retry job queue");
run_queue(arg);
}
static void toggle_debug(uev_t *w, void *arg, int _)
{
int current = setlogmask(0);
if (current == logmask)
setlogmask(LOG_UPTO(LOG_DEBUG));
else
setlogmask(logmask);
}
static void inotify_cb(uev_t *w, void *arg, int _)
{
ssize_t bytes;
int num = 0;
bytes = read(w->fd, buffer, sizeof(buffer));
if (bytes == -1) {
err("read");
return;
}
for (char *p = buffer; p < buffer + bytes;) {
struct inotify_event *event = (struct inotify_event *)p;
char *name = event->name;
if (event->mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVED_TO)) {
dbg("Got inotify event %s 0x%04x", name, event->mask);
if (!should_run(name, '*'))
continue;
num += !!run_job(arg, name);
}
p += sizeof(struct inotify_event) + event->len;
}
if (num)
uev_timer_set(&retry_watcher, retry, 0);
}
static void netlink_cb(uev_t *w, void *arg, int _)
{
struct iovec iov = { buffer, sizeof(buffer) };
struct sockaddr_nl addr;
struct msghdr msg = {
&addr, sizeof(addr),
&iov, 1,
NULL, 0,
0
};
ssize_t bytes;
int sd = w->fd;
dbg("Got netlink event");
/* Empty netlink queue, we just want the event */
while ((bytes = recvmsg(sd, &msg, 0)) > 0)
dbg("Read %ld netlink bytes", bytes);
dbg("Calling run queue");
run_queue(arg);
}
static int usage(const char *arg0, int rc)
{
printf("Usage:\n"
" %s [-dh] [-l LVL] [-t SEC] QUEUE\n"
"Options:\n"
" -d Log to stderr as well\n"
" -h This help text\n"
" -l LVL Set log level: none, err, warn, notice*, info, debug\n"
" -t SEC Retry timer in seconds [10, 604800], default: %d\n"
"\n"
"Run jobs from QUEUE. Triggers on inotify of new jobs, route changes, and\n"
"retries failing jobs every minute until the queue has been emtied.\n"
"Use SIGHUP to trigger a manual retry.\n"
"Use SIGUSR1 to toggle debug messages at runtime.\n", arg0, RETRY_TIMER);
return rc;
}
int main(int argc, char *argv[])
{
struct sockaddr_nl sa = { 0 };
uev_t inotify_watcher;
uev_t netlink_watcher;
uev_t sigusr1_watcher;
uev_t sighup_watcher;
int logopt = LOG_PID;
int wd, sd, fd, c;
char *queue;
uev_ctx_t ctx;
int rc = 0;
while ((c = getopt(argc, argv, "dhl:t:")) != EOF) {
switch (c) {
case 'd':
logopt |= LOG_PERROR;
break;
case 'h':
return usage(argv[0], 0);
case 'l':
logmask = logmask_from_str(optarg);
if (logmask < 0) {
fprintf(stderr, "Invalid loglevel '%s'\n\n", optarg);
return usage(argv[0], 1);
}
break;
case 't':
retry = atoi(optarg);
if (retry < 10 || retry > 604800) {
fprintf(stderr, "Invalid value %d, accepted [10, 604800]", retry);
return 1;
}
break;
default:
return usage(argv[0], 1);
}
}
if (optind >= argc)
return usage(argv[0], 1);
queue = argv[optind];
retry *= 1000;
if (access(queue, X_OK)) {
fprintf(stderr, "Cannot find job directory %s, errno %d: %s\n",
queue, errno, strerror(errno));
return 1;
}
/*
* We close stdin, while leaving stdout et stderr open so a user
* can redirect output from us to a logger process, or
* similar.
*/
close(STDIN_FILENO);
/* The logs of this program go to syslog w/ regular daemon facility */
openlog(NULL, logopt, LOG_DAEMON);
setlogmask(logmask);
fd = inotify_init1(IN_NONBLOCK);
if (fd == -1) {
err("inotify_init");
return 1;
}
wd = inotify_add_watch(fd, queue, IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVED_TO);
if (wd == -1) {
err("inotify_add_watch");
close(fd);
return 1;
}
/* Set up netlink socket for route monitoring */
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
if (sd == -1) {
err("socket");
close(fd);
return 1;
}
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
err("bind");
rc = 1;
goto done;
}
uev_init(&ctx);
if (uev_signal_init(&ctx, &sighup_watcher, signal_cb, queue, SIGHUP) == -1) {
err("uev_signal_init (sighup)");
rc = 1;
goto done;
}
/* Initial delay of 1 sec, lots of other events happening at boot. */
if (uev_timer_init(&ctx, &retry_watcher, timer_cb, queue, 1000, 0) == -1) {
err("uev_timer_init (1000, %d)", retry);
rc = 1;
goto done;
}
if (uev_signal_init(&ctx, &sigusr1_watcher, toggle_debug, NULL, SIGUSR1) == -1) {
err("uev_signal_init (sigusr1)");
rc = 1;
goto done;
}
if (uev_io_init(&ctx, &inotify_watcher, inotify_cb, queue, fd, UEV_READ) == -1) {
err("uev_io_init (inotify)");
rc = 1;
goto done;
}
if (uev_io_init(&ctx, &netlink_watcher, netlink_cb, queue, sd, UEV_READ) == -1) {
err("uev_io_init (netlink)");
rc = 1;
goto done;
}
if (uev_run(&ctx, 0) == -1) {
err("uev_run");
rc = 1;
}
done:
close(fd);
close(sd);
return rc;
}
-76
View File
@@ -1,76 +0,0 @@
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SYSLOG_NAMES
#include <syslog.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/inotify.h>
#include <sys/socket.h>
#include <uev/uev.h>
#include <libite/lite.h>
#define err(fmt, args...) syslog(LOG_ERR, fmt ": %s", ##args, strerror(errno))
#define errx(fmt, args...) syslog(LOG_ERR, fmt, ##args)
#define warn(fmt, args...) syslog(LOG_WARNING, fmt, ": %s", ##args, strerror(errno))
#define warnx(fmt, args...) syslog(LOG_WARNING, fmt, ##args)
#define log(fmt, args...) syslog(LOG_NOTICE, fmt, ##args)
#define dbg(fmt, args...) syslog(LOG_DEBUG, fmt, ##args)
/*
* Allow SNN and KNN style jobs, for inotyify_cb() we also allow
* a type '*' just to figure out if a job should be archived in
* the done directory.
*/
static inline int should_run(const char *name, int type)
{
if (!name || strlen(name) < 3)
return 0;
if (isdigit(name[1]) && isdigit(name[2])) {
if (type == '*') {
switch (name[0]) {
case 'K':
case 'S':
return 1;
default:
goto done;
}
}
switch (type) {
case 'K':
case 'S':
break;
default:
return 0;
}
dbg("name:%s type:'%c' => run:%d", name, type, type == name[0]);
return type == name[0];
}
done:
errx("unsupported script %s, must follow pattern SNN/KNN", name);
return 0;
}
static inline int logmask_from_str(const char *str)
{
const CODE *code;
for (code = prioritynames; code->c_name; code++)
if (!strcmp(str, code->c_name))
return LOG_UPTO(code->c_val);
return -1;
}