summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-04-27 11:26:47 +0200
committerAnthony G. Basile <blueness@gentoo.org>2015-05-26 11:26:45 -0400
commit0c804867b569142ffd07a13c6c350eca35cd81af (patch)
treeb32213a87e5fcd8235c71920deaa688288724a3c /src
parent818b85cb3bfeca3429e2b010e3437d4e532fcb4c (diff)
udevd: worker - make refcounting clearer
Take and drop explicit references where it makes sense. Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
Diffstat (limited to 'src')
-rw-r--r--src/udev/udevd.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index cc96a43b1c..8be9d136c5 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -147,6 +147,7 @@ static struct worker *worker_ref(struct worker *worker) {
static void worker_cleanup(struct worker *worker) {
udev_list_node_remove(&worker->node);
udev_monitor_unref(worker->monitor);
+ udev_unref(worker->udev);
children--;
free(worker);
}
@@ -169,9 +170,36 @@ static void worker_list_cleanup(struct udev *udev) {
}
}
+static int worker_new(struct worker **ret, struct udev *udev, struct udev_monitor *worker_monitor, pid_t pid) {
+ struct worker *worker;
+
+ assert(ret);
+ assert(udev);
+ assert(worker_monitor);
+ assert(pid > 1);
+
+ worker = new0(struct worker, 1);
+ if (!worker)
+ return -ENOMEM;
+
+ /* worker + event reference */
+ worker->refcount = 2;
+ worker->udev = udev_ref(udev);
+ /* close monitor, but keep address around */
+ udev_monitor_disconnect(worker_monitor);
+ worker->monitor = udev_monitor_ref(worker_monitor);
+ worker->pid = pid;
+ udev_list_node_append(&worker->node, &worker_list);
+ children++;
+
+ *ret = worker;
+
+ return 0;
+}
+
static void worker_spawn(struct event *event) {
struct udev *udev = event->udev;
- struct udev_monitor *worker_monitor;
+ _cleanup_udev_monitor_unref_ struct udev_monitor *worker_monitor = NULL;
pid_t pid;
/* listen for new events */
@@ -368,40 +396,28 @@ out:
close(worker_watch[WRITE_END]);
udev_rules_unref(rules);
udev_builtin_exit(udev);
- udev_monitor_unref(worker_monitor);
udev_unref(udev);
log_close();
exit(rc);
}
case -1:
- udev_monitor_unref(worker_monitor);
event->state = EVENT_QUEUED;
log_error_errno(errno, "fork of child failed: %m");
break;
default:
{
struct worker *worker;
+ int r;
- worker = new0(struct worker, 1);
- if (!worker) {
- udev_monitor_unref(worker_monitor);
+ r = worker_new(&worker, udev, worker_monitor, pid);
+ if (r < 0)
return;
- }
- /* worker + event reference */
- worker->refcount = 2;
- worker->udev = udev;
- /* close monitor, but keep address around */
- udev_monitor_disconnect(worker_monitor);
- worker->monitor = worker_monitor;
- worker->pid = pid;
worker->state = WORKER_RUNNING;
worker->event_start_usec = now(CLOCK_MONOTONIC);
worker->event_warned = false;
worker->event = event;
event->state = EVENT_RUNNING;
- udev_list_node_append(&worker->node, &worker_list);
- children++;
log_debug("seq %llu forked new worker ["PID_FMT"]", udev_device_get_seqnum(event->dev), pid);
break;
}