udevd.c revision e918a1b5a94f270186dca59156354acd2a596494
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Copyright (C) 2009 Canonical Ltd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * This program is free software: you can redistribute it and/or modify
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * it under the terms of the GNU General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the Free Software Foundation, either version 2 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * This program is distributed in the hope that it will be useful,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * but WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * GNU General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * You should have received a copy of the GNU General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * along with this program. If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringvoid udev_main_log(struct udev *udev, int priority,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *file, int line, const char *fn,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_metav(priority, file, line, fn, format, args);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned long long int delaying_seqnum;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned long long int seqnum;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackstatic inline struct event *node_to_event(struct udev_list_node *node)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackstatic void event_queue_cleanup(struct udev *udev, enum event_state type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/* passed from worker to main process */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic inline struct worker *node_to_worker(struct udev_list_node *node)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return container_of(node, struct worker, node);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void event_queue_delete(struct event *event)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic struct worker *worker_ref(struct worker *worker)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void worker_cleanup(struct worker *worker)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void worker_unref(struct worker *worker)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("worker [%u] cleaned up", worker->pid);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void worker_list_cleanup(struct udev *udev)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach_safe(loop, tmp, &worker_list) {
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering struct worker *worker = node_to_worker(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* listen for new events */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering worker_monitor = udev_monitor_new_from_netlink(udev, NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* allow the main daemon netlink address to send devices to the worker */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_monitor_allow_unicast_sender(worker_monitor, monitor);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_monitor_enable_receiving(worker_monitor);
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering /* worker + event reference */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct epoll_event ep_signal, ep_monitor;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* take initial device from queue */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memzero(&ep_signal, sizeof(struct epoll_event));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fd_monitor = udev_monitor_get_fd(worker_monitor);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memzero(&ep_monitor, sizeof(struct epoll_event));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_monitor, &ep_monitor) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("fail to add fds to epoll: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* request TERM signal if parent exits */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* reset OOM score, we only protect the main daemon */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering write_string_file("/proc/self/oom_score_adj", "0");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("seq %llu running", udev_device_get_seqnum(dev));
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* needed for SIGCHLD/SIGTERM in spawn() */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Take a "read lock" on the device node; this establishes
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * a concept of device "ownership" to serialize device
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * access. External processes holding a "write lock" will
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * cause udev to skip the event handling; in the case udev
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * acquired the lock, the external process will block until
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * udev has finished its event handling.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kabi_> since we make check - device seems unused - we try
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * ioctl to deactivate - and device is found to be opened
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kay> sure, you try to take a write lock
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kay> if you get it udev is out
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kay> if you can't get it, udev is busy
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kabi_> we cannot deactivate openned device (as it is in-use)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kay> maybe we should just exclude dm from that thing entirely
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * <kabi_> IMHO this sounds like a good plan for this moment
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (streq_ptr("block", udev_device_get_subsystem(dev)) &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering !startswith("dm-", udev_device_get_sysname(dev))) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (streq_ptr("partition", udev_device_get_devtype(d)))
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack fd_lock = open(udev_device_get_devnode(d), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d));
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* apply rules, create node, symlinks */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack udev_event_execute_rules(udev_event, rules, &sigmask_orig);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack udev_event_execute_run(udev_event, &sigmask_orig);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* apply/restore inotify watch */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* send processed event back to libudev listeners */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_monitor_send_device(worker_monitor, NULL, dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* send udevd the result of the event execution */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memzero(&msg, sizeof(struct worker_message));
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack send(worker_watch[WRITE_END], &msg, sizeof(struct worker_message), 0);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_debug("seq %llu processed with %i", udev_device_get_seqnum(dev), err);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* wait for more device messages from main udevd, or term signal */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (i = 0; i < fdcount; i++) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (ev[i].data.fd == fd_monitor && ev[i].events & EPOLLIN) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dev = udev_monitor_receive_device(worker_monitor);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (ev[i].data.fd == fd_signal && ev[i].events & EPOLLIN) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size = read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (size != sizeof(struct signalfd_siginfo))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* close monitor, but keep address around */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering worker->event_start_usec = now(CLOCK_MONOTONIC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_append(&worker->node, &worker_list);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("seq %llu forked new worker [%u]", udev_device_get_seqnum(event->dev), pid);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void event_run(struct event *event)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach(loop, &worker_list) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct worker *worker = node_to_worker(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering count = udev_monitor_send_device(monitor, worker->monitor, event->dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("worker [%u] did not accept message %zi (%m), kill it", worker->pid, count);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering worker->event_start_usec = now(CLOCK_MONOTONIC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("maximum number (%i) of children reached", children);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* start new worker and pass initial device */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int event_queue_insert(struct udev_device *dev)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->seqnum = udev_device_get_seqnum(dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->devpath = udev_device_get_devpath(dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->devpath_len = strlen(event->devpath);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->devpath_old = udev_device_get_devpath_old(dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->devnum = udev_device_get_devnum(dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->is_block = streq("block", udev_device_get_subsystem(dev));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->ifindex = udev_device_get_ifindex(dev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (streq(udev_device_get_subsystem(dev), "firmware"))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("seq %llu queued, '%s' '%s'", udev_device_get_seqnum(dev),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_device_get_action(dev), udev_device_get_subsystem(dev));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_append(&event->node, &event_list);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void worker_kill(struct udev *udev)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach(loop, &worker_list) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct worker *worker = node_to_worker(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/* lookup event for identical, parent, child device */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic bool is_devpath_busy(struct event *event)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* check if queue contains events we depend on */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach(loop, &event_list) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct event *loop_event = node_to_event(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* we already found a later event, earlier can not block us, no need to check again */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (loop_event->seqnum < event->delaying_seqnum)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* event we checked earlier still exists, no need to check again */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (loop_event->seqnum == event->delaying_seqnum)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* found ourself, no later event can block us */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (major(event->devnum) != 0 && event->devnum == loop_event->devnum && event->is_block == loop_event->is_block)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* check network device ifindex */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (event->ifindex != 0 && event->ifindex == loop_event->ifindex)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* check our old name */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (event->devpath_old != NULL && streq(loop_event->devpath, event->devpath_old)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->delaying_seqnum = loop_event->seqnum;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering /* compare devpath */
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering common = MIN(loop_event->devpath_len, event->devpath_len);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering /* one devpath is contained in the other? */
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering if (memcmp(loop_event->devpath, event->devpath, common) != 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* identical device event found */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (loop_event->devpath_len == event->devpath_len) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* devices names might have changed/swapped in the meantime */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (major(event->devnum) != 0 && (event->devnum != loop_event->devnum || event->is_block != loop_event->is_block))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (event->ifindex != 0 && event->ifindex != loop_event->ifindex)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->delaying_seqnum = loop_event->seqnum;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* allow to bypass the dependency tracking */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* parent device event found */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering event->delaying_seqnum = loop_event->seqnum;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack return true;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack /* child device event found */
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack return true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* no matching device */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void event_queue_start(struct udev *udev)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach(loop, &event_list) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct event *event = node_to_event(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* do not start event if parent or child event is still running */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void event_queue_cleanup(struct udev *udev, enum event_state match_type)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering udev_list_node_foreach_safe(loop, tmp, &event_list) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct event *event = node_to_event(loop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (match_type != EVENT_UNDEF && match_type != event->state)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void worker_returned(int fd_worker)
const char *str;
goto out;
goto out;
stop_exec_queue = true;
stop_exec_queue = false;
reload = true;
char *key;
char *val;
children_max = i;
udev_exit = true;
out:
char *buf;
int fd;
if (fd >= 0) {
switch (signo) {
case SIGINT:
case SIGTERM:
udev_exit = true;
case SIGCHLD:
int status;
if (pid <= 0)
case SIGHUP:
reload = true;
int fd, n;
n = sd_listen_fds(true);
if (ctrl >= 0)
if (netlink >= 0)
* udev.children-max=<number of workers> events are fully serialized if set to 1
char *w, *state;
size_t l;
char *s, *opt;
s = strndup(w, l);
opt = s;
int prio;
free(s);
int daemonize = false;
goto exit;
log_open();
int option;
switch (option) {
daemonize = true;
debug = true;
resolve_names = 0;
goto exit;
goto exit;
goto exit;
goto exit;
if (getuid() != 0) {
goto exit;
if (daemonize) {
int fd;
if (fd >= 0) {
goto exit;
goto exit;
goto exit;
goto exit;
goto exit;
goto exit;
if (daemonize) {
switch (pid) {
goto exit;
goto exit_daemonize;
setsid();
if (!debug) {
int fd;
if (fd >= 0) {
if (fd_inotify < 0) {
goto exit;
if (fd_signal < 0) {
goto exit;
goto exit;
goto exit;
if (fd_ep < 0) {
goto exit;
goto exit;
if (children_max <= 0) {
if (rc < 0)
int fdcount;
int timeout;
if (udev_exit) {
if (fd_ctrl >= 0) {
if (fd_inotify >= 0) {
if (udev_cgroup)
int fd;
if (fd >= 0)
if (fdcount < 0)
if (fdcount == 0) {
if (udev_exit) {
log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
for (i = 0; i < fdcount; i++) {
is_worker = true;
is_netlink = true;
is_signal = true;
is_inotify = true;
is_ctrl = true;
reload = true;
reload = true;
if (reload) {
reload = false;
if (is_worker)
if (is_netlink) {
if (is_signal) {
if (udev_exit)
if (is_inotify)
if (is_ctrl)
exit:
if (fd_ep >= 0)
if (fd_signal >= 0)
label_finish();
log_close();
return rc;