mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 23:51:28 +03:00
Merge pull request #43 from teg/udev-forking-rework
udev forking/socket-passing rework
This commit is contained in:
commit
1635b34e15
@ -144,6 +144,22 @@ static bool udev_has_devtmpfs(struct udev *udev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void monitor_set_nl_address(struct udev_monitor *udev_monitor) {
|
||||
union sockaddr_union snl;
|
||||
socklen_t addrlen;
|
||||
int r;
|
||||
|
||||
assert(udev_monitor);
|
||||
|
||||
/* get the address the kernel has assigned us
|
||||
* it is usually, but not necessarily the pid
|
||||
*/
|
||||
addrlen = sizeof(struct sockaddr_nl);
|
||||
r = getsockname(udev_monitor->sock, &snl.sa, &addrlen);
|
||||
if (r >= 0)
|
||||
udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
|
||||
}
|
||||
|
||||
struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd)
|
||||
{
|
||||
struct udev_monitor *udev_monitor;
|
||||
@ -183,7 +199,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c
|
||||
|
||||
if (fd < 0) {
|
||||
udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
|
||||
if (udev_monitor->sock == -1) {
|
||||
if (udev_monitor->sock < 0) {
|
||||
log_debug_errno(errno, "error getting socket: %m");
|
||||
free(udev_monitor);
|
||||
return NULL;
|
||||
@ -191,6 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c
|
||||
} else {
|
||||
udev_monitor->bound = true;
|
||||
udev_monitor->sock = fd;
|
||||
monitor_set_nl_address(udev_monitor);
|
||||
}
|
||||
|
||||
udev_monitor->snl.nl.nl_family = AF_NETLINK;
|
||||
@ -366,6 +383,7 @@ int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct
|
||||
udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* udev_monitor_enable_receiving:
|
||||
* @udev_monitor: the monitor which should receive events
|
||||
@ -388,19 +406,9 @@ _public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
|
||||
udev_monitor->bound = true;
|
||||
}
|
||||
|
||||
if (err >= 0) {
|
||||
union sockaddr_union snl;
|
||||
socklen_t addrlen;
|
||||
|
||||
/*
|
||||
* get the address the kernel has assigned us
|
||||
* it is usually, but not necessarily the pid
|
||||
*/
|
||||
addrlen = sizeof(struct sockaddr_nl);
|
||||
err = getsockname(udev_monitor->sock, &snl.sa, &addrlen);
|
||||
if (err == 0)
|
||||
udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
|
||||
} else {
|
||||
if (err >= 0)
|
||||
monitor_set_nl_address(udev_monitor);
|
||||
else {
|
||||
log_debug_errno(errno, "bind failed: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "missing.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "udev.h"
|
||||
#include "udev-util.h"
|
||||
|
||||
@ -79,7 +80,6 @@ int main(int argc, char *argv[]) {
|
||||
char syspath[UTIL_PATH_SIZE];
|
||||
const char *devpath;
|
||||
const char *action;
|
||||
sigset_t mask, sigmask_orig;
|
||||
int err;
|
||||
|
||||
err = fake_filesystems();
|
||||
@ -93,8 +93,6 @@ int main(int argc, char *argv[]) {
|
||||
log_debug("version %s", VERSION);
|
||||
mac_selinux_init("/dev");
|
||||
|
||||
sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
|
||||
|
||||
action = argv[1];
|
||||
if (action == NULL) {
|
||||
log_error("action missing");
|
||||
@ -118,8 +116,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
event = udev_event_new(dev);
|
||||
|
||||
sigfillset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, &sigmask_orig);
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) == 0);
|
||||
|
||||
/* do what devtmpfs usually provides us */
|
||||
if (udev_device_get_devnode(dev) != NULL) {
|
||||
@ -142,11 +139,9 @@ int main(int argc, char *argv[]) {
|
||||
udev_event_execute_rules(event,
|
||||
3 * USEC_PER_SEC, USEC_PER_SEC,
|
||||
NULL,
|
||||
rules,
|
||||
&sigmask_orig);
|
||||
rules);
|
||||
udev_event_execute_run(event,
|
||||
3 * USEC_PER_SEC, USEC_PER_SEC,
|
||||
NULL);
|
||||
3 * USEC_PER_SEC, USEC_PER_SEC);
|
||||
out:
|
||||
mac_selinux_finish();
|
||||
|
||||
|
@ -385,7 +385,7 @@ out:
|
||||
}
|
||||
|
||||
static int spawn_exec(struct udev_event *event,
|
||||
const char *cmd, char *const argv[], char **envp, const sigset_t *sigmask,
|
||||
const char *cmd, char *const argv[], char **envp,
|
||||
int fd_stdout, int fd_stderr) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
@ -413,9 +413,8 @@ static int spawn_exec(struct udev_event *event,
|
||||
/* terminate child in case parent goes away */
|
||||
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||
|
||||
/* restore original udev sigmask before exec */
|
||||
if (sigmask)
|
||||
sigprocmask(SIG_SETMASK, sigmask, NULL);
|
||||
/* restore sigmask before exec */
|
||||
(void) reset_signal_mask();
|
||||
|
||||
execve(argv[0], argv, envp);
|
||||
|
||||
@ -699,7 +698,7 @@ out:
|
||||
int udev_event_spawn(struct udev_event *event,
|
||||
usec_t timeout_usec,
|
||||
usec_t timeout_warn_usec,
|
||||
const char *cmd, char **envp, const sigset_t *sigmask,
|
||||
const char *cmd, char **envp,
|
||||
char *result, size_t ressize) {
|
||||
int outpipe[2] = {-1, -1};
|
||||
int errpipe[2] = {-1, -1};
|
||||
@ -749,7 +748,7 @@ int udev_event_spawn(struct udev_event *event,
|
||||
|
||||
log_debug("starting '%s'", cmd);
|
||||
|
||||
spawn_exec(event, cmd, argv, envp, sigmask,
|
||||
spawn_exec(event, cmd, argv, envp,
|
||||
outpipe[WRITE_END], errpipe[WRITE_END]);
|
||||
|
||||
_exit(2 );
|
||||
@ -811,8 +810,7 @@ static int rename_netif(struct udev_event *event) {
|
||||
void udev_event_execute_rules(struct udev_event *event,
|
||||
usec_t timeout_usec, usec_t timeout_warn_usec,
|
||||
struct udev_list *properties_list,
|
||||
struct udev_rules *rules,
|
||||
const sigset_t *sigmask) {
|
||||
struct udev_rules *rules) {
|
||||
struct udev_device *dev = event->dev;
|
||||
|
||||
if (udev_device_get_subsystem(dev) == NULL)
|
||||
@ -828,8 +826,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
|
||||
udev_rules_apply_to_event(rules, event,
|
||||
timeout_usec, timeout_warn_usec,
|
||||
properties_list,
|
||||
sigmask);
|
||||
properties_list);
|
||||
|
||||
if (major(udev_device_get_devnum(dev)) != 0)
|
||||
udev_node_remove(dev);
|
||||
@ -847,8 +844,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
|
||||
udev_rules_apply_to_event(rules, event,
|
||||
timeout_usec, timeout_warn_usec,
|
||||
properties_list,
|
||||
sigmask);
|
||||
properties_list);
|
||||
|
||||
/* rename a new network interface, if needed */
|
||||
if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") &&
|
||||
@ -911,7 +907,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
}
|
||||
}
|
||||
|
||||
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigmask) {
|
||||
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) {
|
||||
struct udev_list_entry *list_entry;
|
||||
|
||||
udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
|
||||
@ -934,7 +930,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
|
||||
|
||||
udev_event_apply_format(event, cmd, program, sizeof(program));
|
||||
envp = udev_device_get_properties_envp(event->dev);
|
||||
udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, NULL, 0);
|
||||
udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +633,7 @@ static int import_file_into_properties(struct udev_device *dev, const char *file
|
||||
static int import_program_into_properties(struct udev_event *event,
|
||||
usec_t timeout_usec,
|
||||
usec_t timeout_warn_usec,
|
||||
const char *program, const sigset_t *sigmask) {
|
||||
const char *program) {
|
||||
struct udev_device *dev = event->dev;
|
||||
char **envp;
|
||||
char result[UTIL_LINE_SIZE];
|
||||
@ -641,7 +641,7 @@ static int import_program_into_properties(struct udev_event *event,
|
||||
int err;
|
||||
|
||||
envp = udev_device_get_properties_envp(dev);
|
||||
err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result));
|
||||
err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, result, sizeof(result));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -1895,8 +1895,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
|
||||
struct udev_event *event,
|
||||
usec_t timeout_usec,
|
||||
usec_t timeout_warn_usec,
|
||||
struct udev_list *properties_list,
|
||||
const sigset_t *sigmask) {
|
||||
struct udev_list *properties_list) {
|
||||
struct token *cur;
|
||||
struct token *rule;
|
||||
enum escape_type esc = ESCAPE_UNSET;
|
||||
@ -2132,7 +2131,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
|
||||
rules_str(rules, rule->rule.filename_off),
|
||||
rule->rule.filename_line);
|
||||
|
||||
if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result)) < 0) {
|
||||
if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, result, sizeof(result)) < 0) {
|
||||
if (cur->key.op != OP_NOMATCH)
|
||||
goto nomatch;
|
||||
} else {
|
||||
@ -2168,7 +2167,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
|
||||
rules_str(rules, rule->rule.filename_off),
|
||||
rule->rule.filename_line);
|
||||
|
||||
if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import, sigmask) != 0)
|
||||
if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import) != 0)
|
||||
if (cur->key.op != OP_NOMATCH)
|
||||
goto nomatch;
|
||||
break;
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "sd-rtnl.h"
|
||||
@ -73,8 +72,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules);
|
||||
bool udev_rules_check_timestamp(struct udev_rules *rules);
|
||||
int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event,
|
||||
usec_t timeout_usec, usec_t timeout_warn_usec,
|
||||
struct udev_list *properties_list,
|
||||
const sigset_t *sigmask);
|
||||
struct udev_list *properties_list);
|
||||
int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
|
||||
|
||||
/* udev-event.c */
|
||||
@ -86,14 +84,13 @@ int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
|
||||
int udev_event_spawn(struct udev_event *event,
|
||||
usec_t timeout_usec,
|
||||
usec_t timeout_warn_usec,
|
||||
const char *cmd, char **envp, const sigset_t *sigmask,
|
||||
const char *cmd, char **envp,
|
||||
char *result, size_t ressize);
|
||||
void udev_event_execute_rules(struct udev_event *event,
|
||||
usec_t timeout_usec, usec_t timeout_warn_usec,
|
||||
struct udev_list *properties_list,
|
||||
struct udev_rules *rules,
|
||||
const sigset_t *sigset);
|
||||
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigset);
|
||||
struct udev_rules *rules);
|
||||
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec);
|
||||
int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]);
|
||||
|
||||
/* udev-watch.c */
|
||||
|
@ -135,8 +135,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
|
||||
udev_event_execute_rules(event,
|
||||
60 * USEC_PER_SEC, 20 * USEC_PER_SEC,
|
||||
NULL,
|
||||
rules,
|
||||
&sigmask_orig);
|
||||
rules);
|
||||
|
||||
udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev))
|
||||
printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
|
||||
|
212
src/udev/udevd.c
212
src/udev/udevd.c
@ -42,6 +42,8 @@
|
||||
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "signal-util.h"
|
||||
#include "event-util.h"
|
||||
#include "rtnl-util.h"
|
||||
#include "cgroup-util.h"
|
||||
@ -67,9 +69,8 @@ typedef struct Manager {
|
||||
sd_event *event;
|
||||
Hashmap *workers;
|
||||
struct udev_list_node events;
|
||||
char *cgroup;
|
||||
const char *cgroup;
|
||||
pid_t pid; /* the process that originally allocated the manager object */
|
||||
sigset_t sigmask_orig;
|
||||
|
||||
struct udev_rules *rules;
|
||||
struct udev_list properties;
|
||||
@ -306,7 +307,6 @@ static void manager_free(Manager *manager) {
|
||||
|
||||
udev_list_cleanup(&manager->properties);
|
||||
udev_rules_unref(manager->rules);
|
||||
free(manager->cgroup);
|
||||
|
||||
safe_close(manager->fd_inotify);
|
||||
safe_close_pair(manager->worker_watch);
|
||||
@ -448,12 +448,10 @@ static void worker_spawn(Manager *manager, struct event *event) {
|
||||
udev_event_execute_rules(udev_event,
|
||||
arg_event_timeout_usec, arg_event_timeout_warn_usec,
|
||||
&manager->properties,
|
||||
manager->rules,
|
||||
&manager->sigmask_orig);
|
||||
manager->rules);
|
||||
|
||||
udev_event_execute_run(udev_event,
|
||||
arg_event_timeout_usec, arg_event_timeout_warn_usec,
|
||||
&manager->sigmask_orig);
|
||||
arg_event_timeout_usec, arg_event_timeout_warn_usec);
|
||||
|
||||
if (udev_event->rtnl)
|
||||
/* in case rtnl was initialized */
|
||||
@ -1263,38 +1261,91 @@ static int on_post(sd_event_source *s, void *userdata) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int systemd_fds(int *rctrl, int *rnetlink) {
|
||||
int ctrl = -1, netlink = -1;
|
||||
int fd, n;
|
||||
static int listen_fds(int *rctrl, int *rnetlink) {
|
||||
_cleanup_udev_unref_ struct udev *udev = NULL;
|
||||
int ctrl_fd = -1, netlink_fd = -1;
|
||||
int fd, n, r;
|
||||
|
||||
assert(rctrl);
|
||||
assert(rnetlink);
|
||||
|
||||
n = sd_listen_fds(true);
|
||||
if (n <= 0)
|
||||
return -1;
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) {
|
||||
if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1)) {
|
||||
if (ctrl >= 0)
|
||||
return -1;
|
||||
ctrl = fd;
|
||||
if (ctrl_fd >= 0)
|
||||
return -EINVAL;
|
||||
ctrl_fd = fd;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1)) {
|
||||
if (netlink >= 0)
|
||||
return -1;
|
||||
netlink = fd;
|
||||
if (netlink_fd >= 0)
|
||||
return -EINVAL;
|
||||
netlink_fd = fd;
|
||||
continue;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctrl < 0 || netlink < 0)
|
||||
return -1;
|
||||
if (ctrl_fd < 0) {
|
||||
_cleanup_udev_ctrl_unref_ struct udev_ctrl *ctrl = NULL;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return -ENOMEM;
|
||||
|
||||
ctrl = udev_ctrl_new(udev);
|
||||
if (!ctrl)
|
||||
return log_error_errno(EINVAL, "error initializing udev control socket");
|
||||
|
||||
r = udev_ctrl_enable_receiving(ctrl);
|
||||
if (r < 0)
|
||||
return log_error_errno(EINVAL, "error binding udev control socket");
|
||||
|
||||
fd = udev_ctrl_get_fd(ctrl);
|
||||
if (fd < 0)
|
||||
return log_error_errno(EIO, "could not get ctrl fd");
|
||||
|
||||
ctrl_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (ctrl_fd < 0)
|
||||
return log_error_errno(errno, "could not dup ctrl fd: %m");
|
||||
}
|
||||
|
||||
if (netlink_fd < 0) {
|
||||
_cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL;
|
||||
|
||||
if (!udev) {
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
monitor = udev_monitor_new_from_netlink(udev, "kernel");
|
||||
if (!monitor)
|
||||
return log_error_errno(EINVAL, "error initializing netlink socket");
|
||||
|
||||
(void) udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024);
|
||||
|
||||
r = udev_monitor_enable_receiving(monitor);
|
||||
if (r < 0)
|
||||
return log_error_errno(EINVAL, "error binding netlink socket");
|
||||
|
||||
fd = udev_monitor_get_fd(monitor);
|
||||
if (fd < 0)
|
||||
return log_error_errno(netlink_fd, "could not get uevent fd: %m");
|
||||
|
||||
netlink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (ctrl_fd < 0)
|
||||
return log_error_errno(errno, "could not dup netlink fd: %m");
|
||||
}
|
||||
|
||||
*rctrl = ctrl_fd;
|
||||
*rnetlink = netlink_fd;
|
||||
|
||||
log_debug("ctrl=%i netlink=%i", ctrl, netlink);
|
||||
*rctrl = ctrl;
|
||||
*rnetlink = netlink;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1439,11 +1490,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int manager_new(Manager **ret) {
|
||||
static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) {
|
||||
_cleanup_(manager_freep) Manager *manager = NULL;
|
||||
int r, fd_ctrl, fd_uevent;
|
||||
int r, fd_worker, one = 1;
|
||||
|
||||
assert(ret);
|
||||
assert(fd_ctrl >= 0);
|
||||
assert(fd_uevent >= 0);
|
||||
|
||||
manager = new0(Manager, 1);
|
||||
if (!manager)
|
||||
@ -1466,57 +1519,15 @@ static int manager_new(Manager **ret) {
|
||||
udev_list_node_init(&manager->events);
|
||||
udev_list_init(manager->udev, &manager->properties, true);
|
||||
|
||||
r = systemd_fds(&fd_ctrl, &fd_uevent);
|
||||
if (r >= 0) {
|
||||
/* get control and netlink socket from systemd */
|
||||
manager->ctrl = udev_ctrl_new_from_fd(manager->udev, fd_ctrl);
|
||||
if (!manager->ctrl)
|
||||
return log_error_errno(EINVAL, "error taking over udev control socket");
|
||||
manager->cgroup = cgroup;
|
||||
|
||||
manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", fd_uevent);
|
||||
if (!manager->monitor)
|
||||
return log_error_errno(EINVAL, "error taking over netlink socket");
|
||||
manager->ctrl = udev_ctrl_new_from_fd(manager->udev, fd_ctrl);
|
||||
if (!manager->ctrl)
|
||||
return log_error_errno(EINVAL, "error taking over udev control socket");
|
||||
|
||||
/* get our own cgroup, we regularly kill everything udev has left behind */
|
||||
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &manager->cgroup);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "failed to get cgroup: %m");
|
||||
} else {
|
||||
/* open control and netlink socket */
|
||||
manager->ctrl = udev_ctrl_new(manager->udev);
|
||||
if (!manager->ctrl)
|
||||
return log_error_errno(EINVAL, "error initializing udev control socket");
|
||||
|
||||
fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
|
||||
|
||||
manager->monitor = udev_monitor_new_from_netlink(manager->udev, "kernel");
|
||||
if (!manager->monitor)
|
||||
return log_error_errno(EINVAL, "error initializing netlink socket");
|
||||
|
||||
fd_uevent = udev_monitor_get_fd(manager->monitor);
|
||||
|
||||
(void) udev_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
|
||||
}
|
||||
|
||||
r = udev_monitor_enable_receiving(manager->monitor);
|
||||
if (r < 0)
|
||||
return log_error_errno(EINVAL, "error binding netlink socket");
|
||||
|
||||
r = udev_ctrl_enable_receiving(manager->ctrl);
|
||||
if (r < 0)
|
||||
return log_error_errno(EINVAL, "error binding udev control socket");
|
||||
|
||||
*ret = manager;
|
||||
manager = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_listen(Manager *manager) {
|
||||
sigset_t mask;
|
||||
int r, fd_worker, one = 1;
|
||||
|
||||
assert(manager);
|
||||
manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", fd_uevent);
|
||||
if (!manager->monitor)
|
||||
return log_error_errno(EINVAL, "error taking over netlink socket");
|
||||
|
||||
/* unnamed socket from workers to the main daemon */
|
||||
r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
|
||||
@ -1536,8 +1547,7 @@ static int manager_listen(Manager *manager) {
|
||||
udev_watch_restore(manager->udev);
|
||||
|
||||
/* block and listen to all signals on signalfd */
|
||||
sigfillset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, &manager->sigmask_orig);
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) == 0);
|
||||
|
||||
r = sd_event_default(&manager->event);
|
||||
if (r < 0)
|
||||
@ -1563,7 +1573,7 @@ static int manager_listen(Manager *manager) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error creating watchdog event source: %m");
|
||||
|
||||
r = sd_event_add_io(manager->event, &manager->ctrl_event, udev_ctrl_get_fd(manager->ctrl), EPOLLIN, on_ctrl_msg, manager);
|
||||
r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error creating ctrl event source: %m");
|
||||
|
||||
@ -1579,7 +1589,7 @@ static int manager_listen(Manager *manager) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error creating inotify event source: %m");
|
||||
|
||||
r = sd_event_add_io(manager->event, &manager->uevent_event, udev_monitor_get_fd(manager->monitor), EPOLLIN, on_uevent, manager);
|
||||
r = sd_event_add_io(manager->event, &manager->uevent_event, fd_uevent, EPOLLIN, on_uevent, manager);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error creating uevent event source: %m");
|
||||
|
||||
@ -1591,12 +1601,16 @@ static int manager_listen(Manager *manager) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error creating post event source: %m");
|
||||
|
||||
*ret = manager;
|
||||
manager = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *manager = NULL;
|
||||
int r;
|
||||
_cleanup_free_ char *cgroup = NULL;
|
||||
int r, fd_ctrl, fd_uevent;
|
||||
|
||||
log_set_target(LOG_TARGET_AUTO);
|
||||
log_parse_environment();
|
||||
@ -1653,13 +1667,20 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
dev_setup(NULL, UID_INVALID, GID_INVALID);
|
||||
|
||||
r = manager_new(&manager);
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
if (getppid() == 1) {
|
||||
/* get our own cgroup, we regularly kill everything udev has left behind
|
||||
we only do this on systemd systems, and only if we are directly spawned
|
||||
by PID1. otherwise we are not guaranteed to have a dedicated cgroup */
|
||||
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "failed to get cgroup: %m");
|
||||
}
|
||||
|
||||
r = udev_rules_apply_static_dev_perms(manager->rules);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "failed to apply permissions on static device nodes: %m");
|
||||
r = listen_fds(&fd_ctrl, &fd_uevent);
|
||||
if (r < 0) {
|
||||
r = log_error_errno(r, "could not listen on fds: %m");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (arg_daemonize) {
|
||||
pid_t pid;
|
||||
@ -1682,14 +1703,21 @@ int main(int argc, char *argv[]) {
|
||||
setsid();
|
||||
|
||||
write_string_file("/proc/self/oom_score_adj", "-1000");
|
||||
} else
|
||||
sd_notify(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Processing...");
|
||||
}
|
||||
|
||||
r = manager_listen(manager);
|
||||
r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
|
||||
if (r < 0) {
|
||||
r = log_error_errno(r, "failed to allocate manager object: %m");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
r = udev_rules_apply_static_dev_perms(manager->rules);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "failed to set up fds and listen for events: %m");
|
||||
log_error_errno(r, "failed to apply permissions on static device nodes: %m");
|
||||
|
||||
(void) sd_notify(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Processing...");
|
||||
|
||||
r = sd_event_loop(manager->event);
|
||||
if (r < 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user