Merge branch 'master' into wip-tests

This commit is contained in:
Jacques de Laval
2021-02-25 17:40:23 +01:00
9 changed files with 125 additions and 168 deletions
+3 -3
View File
@@ -43,17 +43,17 @@ static void setup(void *arg)
path = which("/lib/systemd/systemd-udevd");
if (path) {
/* Register udevd as a monitored service */
snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd name:udevd %s "
snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd name:udevd log %s "
"-- Device event managing daemon", path);
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
_pe("Failed registering %s", path);
} else {
snprintf(cmd, sizeof(cmd), ":1 [S] log <pid/udevd> "
snprintf(cmd, sizeof(cmd), ":1 [S] <pid/udevd> log "
"udevadm trigger -c add -t devices "
"-- Requesting device events");
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
snprintf(cmd, sizeof(cmd), ":2 [S] log <pid/udevd> "
snprintf(cmd, sizeof(cmd), ":2 [S] <pid/udevd> log "
"udevadm trigger -c add -t subsystems "
"-- Requesting subsystem events");
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
+7 -19
View File
@@ -149,36 +149,26 @@ static void pidfile_handle_dir(struct iwatch *iw, char *dir, char *name, int mas
static void pidfile_callback(void *arg, int fd, int events)
{
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
struct inotify_event *ev;
ssize_t sz, off;
size_t buflen = 8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1;
char *buf;
buf= malloc(buflen);
if (!buf) {
_pe("Failed allocating buffer for inotify events");
return;
}
_d("Entering ... reading %zu bytes into ev_buf[]", buflen - 1);
sz = read(fd, buf, buflen - 1);
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
if (sz <= 0) {
_pe("invalid inotify event");
goto done;
return;
}
buf[sz] = 0;
_d("Read %zd bytes, processing ...", sz);
ev_buf[sz] = 0;
off = 0;
for (off = 0; off < sz; off += sizeof(*ev) + ev->len) {
struct iwatch_path *iwp;
ev = (struct inotify_event *)&buf[off];
_d("path %s, event: 0x%08x", ev->name, ev->mask);
ev = (struct inotify_event *)&ev_buf[off];
if (!ev->mask)
continue;
_d("name %s, event: 0x%08x", ev->name, ev->mask);
/* Find base path for this event */
iwp = iwatch_find_by_wd(&iw_pidfile, ev->wd);
if (!iwp)
@@ -197,8 +187,6 @@ static void pidfile_callback(void *arg, int fd, int events)
if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO))
pidfile_update_conds(iwp->path, ev->name, ev->mask);
}
done:
free(buf);
}
/*
+59 -100
View File
@@ -34,6 +34,7 @@
#include "finit.h"
#include "cond.h"
#include "iwatch.h"
#include "service.h"
#include "tty.h"
#include "helpers.h"
@@ -53,7 +54,9 @@ struct conf_change {
char *name;
};
static uev_t w1, w2, w3, w4;
static struct iwatch iw_conf;
static uev_t etcw;
static TAILQ_HEAD(head, conf_change) conf_change_list = TAILQ_HEAD_INITIALIZER(conf_change_list);
static int parse_conf(char *file);
@@ -680,8 +683,9 @@ int conf_reload(void)
for (i = 0; i < gl.gl_pathc; i++) {
char *path = gl.gl_pathv[i];
size_t len;
char *rp = NULL;
struct stat st;
size_t len;
/* Check that it's an actual file ... beyond any symlinks */
if (lstat(path, &st)) {
@@ -697,25 +701,22 @@ int conf_reload(void)
/* Check for dangling symlinks */
if (S_ISLNK(st.st_mode)) {
char *rp;
rp = realpath(path, NULL);
path = rp = realpath(path, NULL);
if (!rp) {
logit(LOG_WARNING, "Skipping %s, dangling symlink: %s", path, strerror(errno));
continue;
}
free(rp);
}
/* Check that file ends with '.conf' */
len = strlen(path);
if (len < 6 || strcmp(&path[len - 5], ".conf")) {
if (len < 6 || strcmp(&path[len - 5], ".conf"))
_d("Skipping %s, not a valid .conf ... ", path);
continue;
}
else
parse_conf_dynamic(path);
parse_conf_dynamic(path);
if (rp)
free(rp);
}
globfree(&gl);
@@ -742,6 +743,7 @@ static struct conf_change *conf_find(char *file)
struct conf_change *node, *tmp;
TAILQ_FOREACH_SAFE(node, &conf_change_list, link, tmp) {
_d("file: %s vs changed file: %s", file, node->name);
if (string_compare(node->name, file))
return node;
}
@@ -768,13 +770,15 @@ static void drop_changes(void)
drop_change(node);
}
static int do_change(char *name, uint32_t mask)
static int do_change(char *dir, char *name, uint32_t mask)
{
char path[strlen(dir) + strlen(name) + 2];
struct conf_change *node;
_d("Change detected for %s, mask 0x%08x", name, mask);
snprintf(path, sizeof(path), "%s%s", dir, name);
_d("path: %s", path);
node = conf_find(name);
node = conf_find(path);
if (mask & (IN_DELETE | IN_MOVED_FROM)) {
drop_change(node);
return 0;
@@ -789,14 +793,14 @@ static int do_change(char *name, uint32_t mask)
if (!node)
return 1;
node->name = strdup(name);
node->name = strdup(path);
if (!node->name) {
free(node);
return 1;
}
_d("Event registered for %s, mask 0x%x", name, mask);
TAILQ_INSERT_HEAD(&conf_change_list, node,link);
_d("Event registered for %s, mask 0x%x", path, mask);
TAILQ_INSERT_HEAD(&conf_change_list, node, link);
return 0;
}
@@ -811,14 +815,9 @@ int conf_any_change(void)
int conf_changed(char *file)
{
char *ptr;
if (!file)
return 0;
if ((ptr = strrchr(file, '/')))
file = ++ptr;
if (conf_find(file))
return 1;
@@ -829,7 +828,7 @@ static void conf_cb(uev_t *w, void *arg, int events)
{
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
struct inotify_event *ev;
ssize_t sz, len;
ssize_t sz, off;
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
if (sz <= 0) {
@@ -837,17 +836,23 @@ static void conf_cb(uev_t *w, void *arg, int events)
return;
}
ev_buf[sz] = 0;
ev = (struct inotify_event *)ev_buf;
if (arg) {
do_change(arg, ev->mask);
return;
}
for (off = 0; off < sz; off += sizeof(*ev) + ev->len) {
struct iwatch_path *iwp;
for (ev = (void *)ev_buf; sz > (ssize_t)sizeof(*ev);
len = sizeof(*ev) + ev->len, ev = (void *)ev + len, sz -= len) {
if (do_change(ev->name, ev->mask)) {
_pe("conf_monitor: Out of memory");
ev = (struct inotify_event *)&ev_buf[off];
if (!ev->mask)
continue;
_d("name %s, event: 0x%08x", ev->name, ev->mask);
/* Find base path for this event */
iwp = iwatch_find_by_wd(&iw_conf, ev->wd);
if (!iwp)
continue;
if (do_change(iwp->path, ev->name, ev->mask)) {
_pe(" Out of memory");
break;
}
}
@@ -858,82 +863,23 @@ static void conf_cb(uev_t *w, void *arg, int events)
#endif
}
static int add_watcher(uev_ctx_t *ctx, uev_t *w, char *path, uint32_t opt)
{
struct stat st;
uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY | IN_ATTRIB | IN_MOVE;
char *arg = NULL;
int fd, wd;
if (!ctx)
return 0;
if (stat(path, &st)) {
_d("No such file or directory, skipping %s", path);
w->fd = -1;
return 0;
}
if (!S_ISDIR(st.st_mode)) {
arg = strrchr(path, '/');
if (!arg)
arg = path;
else
arg++;
}
if (w->fd >= 0)
close(w->fd);
fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (fd < 0) {
_pe("Failed creating inotify descriptor");
w->fd = -1;
return 1;
}
/*
* Only forward error, don't report error,
* user may not have @path and that's OK
*/
wd = inotify_add_watch(fd, path, mask | opt);
if (wd < 0) {
w->fd = -1;
close(fd);
return 1;
}
if (uev_io_init(ctx, w, conf_cb, arg, fd, UEV_READ)) {
_pe("Failed setting up I/O callback for %s watcher", path);
w->fd = -1;
close(fd);
return 1;
}
_d("Set up inotify watcher for %s ...", path);
return 0;
}
/*
* Set up inotify watcher and load all *.conf in /etc/finit.d/
*/
int conf_monitor(uev_ctx_t *ctx)
int conf_monitor(void)
{
int rc = 0;
/* Skip second run, when called from finit.c in rescue mode */
if (ctx && rescue)
return 0;
/*
* If only one watcher fails, that's OK. A user may have only
* one of /etc/finit.conf or /etc/finit.d in use, and may also
* have or not have symlinks in place. We need to monitor for
* changes to either symlink or target.
*/
rc += add_watcher(ctx, &w1, FINIT_RCSD, 0);
rc += add_watcher(ctx, &w2, FINIT_RCSD "/available/", IN_DONT_FOLLOW);
rc += add_watcher(ctx, &w3, FINIT_RCSD "/enabled/", 0);
rc += add_watcher(ctx, &w4, FINIT_CONF, 0);
rc += iwatch_add(&iw_conf, FINIT_RCSD, IN_ONLYDIR);
rc += iwatch_add(&iw_conf, FINIT_RCSD "/available/", IN_ONLYDIR | IN_DONT_FOLLOW);
rc += iwatch_add(&iw_conf, FINIT_RCSD "/enabled/", IN_ONLYDIR | IN_DONT_FOLLOW);
rc += iwatch_add(&iw_conf, FINIT_CONF, 0);
return rc + conf_reload();
}
@@ -941,12 +887,25 @@ int conf_monitor(uev_ctx_t *ctx)
/*
* Prepare .conf parser and load all .conf files
*/
int conf_init(void)
int conf_init(uev_ctx_t *ctx)
{
hostname = strdup(DEFHOST);
w1.fd = w2.fd = w3.fd = w4.fd = -1;
int fd;
return conf_monitor(NULL);
/* default hostname */
hostname = strdup(DEFHOST);
/* prepare /etc watcher */
fd = iwatch_init(&iw_conf);
if (fd < 0)
return 1;
if (uev_io_init(ctx, &etcw, conf_cb, NULL, fd, UEV_READ)) {
_pe("Failed setting up I/O callback for /etc watcher");
close(fd);
return 1;
}
return 0;
}
/**
+2 -2
View File
@@ -34,11 +34,11 @@ extern struct rlimit global_rlimit[];
int str2rlim(char *str);
char *rlim2str(int rlim);
int conf_init (void);
int conf_init (uev_ctx_t *ctx);
void conf_reload (void);
int conf_any_change (void);
int conf_changed (char *file);
int conf_monitor (uev_ctx_t *ctx);
int conf_monitor (void);
void conf_parse_cmdline (int argc, char *argv[]);
int conf_parse_runlevels (char *runlevels);
+4 -4
View File
@@ -449,7 +449,7 @@ int main(int argc, char *argv[])
/*
* Initialize .conf system and load static /etc/finit.conf.
*/
conf_init();
conf_init(&loop);
/* Base FS up, enable standard SysV init signals */
sig_setup(&loop);
@@ -458,10 +458,10 @@ int main(int argc, char *argv[])
plugin_run_hooks(HOOK_BASEFS_UP);
/*
* Set up inotify watcher for /etc/finit.d and read all .conf
* files to figure out how to bootstrap the system.
* Set up inotify watcher for /etc/finit.conf, /etc/finit.d, and
* their deps, to figure out how to bootstrap the system.
*/
conf_monitor(&loop);
conf_monitor();
_d("Starting initctl API responder ...");
api_init(&loop);
-3
View File
@@ -185,9 +185,6 @@ char *strip_line(char *line)
void enable_progress(int onoff)
{
if (debug)
return;
if (onoff)
progress_style = progress_onoff;
else
+4
View File
@@ -80,6 +80,10 @@ int iwatch_add(struct iwatch *iw, char *file, uint32_t mask)
if (!initialized)
return -1;
if (!fexist(file)) {
_d("No such file or directory, skipping %s", file);
return 0;
}
_d("Adding new watcher for path %s", file);
path = strdup(file);
-1
View File
@@ -85,7 +85,6 @@ void log_debug(void)
screen_init();
}
log_open();
enable_progress(1);
logit(LOG_NOTICE, "Debug mode %s", debug ? "enabled" : "disabled");
}
+46 -36
View File
@@ -620,6 +620,22 @@ static void service_kill(svc_t *svc)
print(2, NULL);
}
/*
* Clean up any lingering state from dead/killed services
*/
static void service_cleanup(svc_t *svc)
{
char *fn;
fn = pid_file(svc);
if (remove(fn) && errno != ENOENT)
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
basename(svc->cmd), fn);
/* No longer running, update books. */
svc->start_time = svc->pid = 0;
}
/**
* service_stop - Stop service
* @svc: Service to stop
@@ -629,7 +645,7 @@ static void service_kill(svc_t *svc)
*/
static int service_stop(svc_t *svc)
{
int res = 0;
int rc = 0;
if (!svc)
return 1;
@@ -657,25 +673,15 @@ static int service_stop(svc_t *svc)
print_desc("Stopping ", svc->desc);
if (!svc_is_sysv(svc)) {
if (svc->pid <= 1)
goto cleanup;
if (svc->pid > 1) {
/* Kill all children in the same proess group, e.g. logit */
rc = kill(-svc->pid, svc->sighalt);
res = kill(-svc->pid, svc->sighalt);
/* PID lost or forking process never really started */
if (res == -1 && ESRCH == errno) {
char *fn;
/* XXX: Same clenup as done by service_monitor(), refactor */
cleanup:
fn = pid_file(svc);
if (remove(fn) && errno != ENOENT)
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
basename(svc->cmd), fn);
/* No longer running, update books. */
svc->start_time = svc->pid = 0;
}
/* PID lost or forking process never really started */
if (rc == -1 && ESRCH == errno)
service_cleanup(svc);
} else
service_cleanup(svc);
} else {
char *args[] = { svc->cmd, "stop", NULL };
pid_t pid;
@@ -689,18 +695,18 @@ static int service_stop(svc_t *svc)
break;
case -1:
_pe("Failed fork() to call sysv script '%s stop'", svc->cmd);
res = 1;
rc = 1;
break;
default:
res = WEXITSTATUS(complete(svc->cmd, pid));
rc = WEXITSTATUS(complete(svc->cmd, pid));
break;
}
}
if (runlevel != 1)
print_result(res);
print_result(rc);
return res;
return rc;
}
/**
@@ -716,6 +722,7 @@ static int service_stop(svc_t *svc)
static int service_restart(svc_t *svc)
{
int do_progress = 1;
pid_t lost = 0;
int rc;
/* Ignore if finit is SIGSTOP'ed */
@@ -742,19 +749,26 @@ static int service_restart(svc_t *svc)
logit(LOG_CONSOLE | LOG_NOTICE, "Restarting %s[%d], sending SIGHUP ...",
svc_ident(svc, NULL, 0), svc->pid);
rc = kill(svc->pid, SIGHUP);
if (rc == -1 && errno == ESRCH) {
/* nobody home, reset internal state machine */
lost = svc->pid;
} else {
/* Declare we're waiting for svc to re-assert/touch its pidfile */
svc_starting(svc);
/* Declare we're waiting for svc to re-assert/touch its pidfile */
svc_starting(svc);
/* Service does not maintain a PID file on its own */
if (svc_has_pidfile(svc)) {
sched_yield();
touch(pid_file(svc));
/* Service does not maintain a PID file on its own */
if (svc_has_pidfile(svc)) {
sched_yield();
touch(pid_file(svc));
}
}
if (do_progress)
print_result(rc);
if (lost)
service_monitor(lost, 0);
return rc;
}
@@ -1159,11 +1173,7 @@ void service_monitor(pid_t lost, int status)
/* Try removing PID file (in case service does not clean up after itself) */
if (svc_is_daemon(svc)) {
char *fn;
fn = pid_file(svc);
if (remove(fn) && errno != ENOENT)
logit(LOG_CRIT, "Failed removing service %s pidfile %s", basename(svc->cmd), fn);
service_cleanup(svc);
} else if (svc_is_runtask(svc)) {
if (WIFEXITED(status) && !WEXITSTATUS(status))
svc->started = 1;
@@ -1172,7 +1182,7 @@ void service_monitor(pid_t lost, int status)
}
/* Terminate any children in the same proess group, e.g. logit */
kill(-svc->pid, SIGTERM);
kill(-svc->pid, SIGKILL);
/* No longer running, update books. */
svc->start_time = svc->pid = 0;