chiark / gitweb /
udevd: fix unref'ing of device in error path
[elogind.git] / udev / udevd.c
index e38c6016499048f0cabda9f10100efad47b702e3..6dc97955d62612e2bedd15db6c633787136a5bc3 100644 (file)
@@ -227,8 +227,10 @@ static void worker_new(struct event *event)
        udev_monitor_enable_receiving(worker_monitor);
 
        worker = calloc(1, sizeof(struct worker));
-       if (worker == NULL)
+       if (worker == NULL) {
+               udev_monitor_unref(worker_monitor);
                return;
+       }
        /* worker + event reference */
        worker->refcount = 2;
        worker->udev = event->udev;
@@ -400,13 +402,13 @@ static void event_run(struct event *event, bool force)
        worker_new(event);
 }
 
-static void event_queue_insert(struct udev_device *dev)
+static int event_queue_insert(struct udev_device *dev)
 {
        struct event *event;
 
        event = calloc(1, sizeof(struct event));
        if (event == NULL)
-               return;
+               return -1;
 
        event->udev = udev_device_get_udev(dev);
        event->dev = dev;
@@ -427,8 +429,10 @@ static void event_queue_insert(struct udev_device *dev)
        /* run all events with a timeout set immediately */
        if (udev_device_get_timeout(dev) > 0) {
                event_run(event, true);
-               return;
+               return 0;
        }
+
+       return 0;
 }
 
 static void worker_kill(struct udev *udev, int retain)
@@ -1006,7 +1010,9 @@ static int init_notify(const char *state)
 
        memset(&msghdr, 0, sizeof(msghdr));
        msghdr.msg_name = &sockaddr;
-       msghdr.msg_namelen = sizeof(struct sockaddr_un);
+       msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e);
+       if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
+               msghdr.msg_namelen = sizeof(struct sockaddr_un);
        msghdr.msg_iov = &iovec;
        msghdr.msg_iovlen = 1;
        msghdr.msg_control = &control;
@@ -1058,7 +1064,7 @@ int main(int argc, char *argv[])
        for (;;) {
                int option;
 
-               option = getopt_long(argc, argv, "cdeDthV", options, NULL);
+               option = getopt_long(argc, argv, "c:deDthV", options, NULL);
                if (option == -1)
                        break;
 
@@ -1347,9 +1353,8 @@ int main(int argc, char *argv[])
 
                        dev = udev_monitor_receive_device(monitor);
                        if (dev != NULL)
-                               event_queue_insert(dev);
-                       else
-                               udev_device_unref(dev);
+                               if (event_queue_insert(dev) < 0)
+                                       udev_device_unref(dev);
                }
 
                /* start new events */