multipath: reference the udev context when starting event queue
authorHannes Reinecke <hare@suse.de>
Tue, 16 Jul 2013 07:13:15 +0000 (09:13 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Tue, 16 Jul 2013 19:52:04 +0000 (21:52 +0200)
The uevent listener is running asynchronously, so it might still
be active and receiving events when the main thread is already
shut down. So it need to take a separate reference to the udev
context to avoid the context becoming invalid while the listener
is running.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/uevent.c
libmultipath/uevent.h
multipathd/main.c

index 0643e14..9ee3ade 100644 (file)
@@ -47,7 +47,6 @@
 #include "list.h"
 #include "uevent.h"
 #include "vector.h"
-#include "config.h"
 
 typedef int (uev_trigger)(struct uevent *, void * trigger_data);
 
@@ -127,11 +126,14 @@ service_uevq(struct list_head *tmpq)
 
 static void uevq_stop(void *arg)
 {
+       struct udev *udev = arg;
+
        condlog(3, "Stopping uev queue");
        pthread_mutex_lock(uevq_lockp);
        my_uev_trigger = NULL;
        pthread_cond_signal(uev_condp);
        pthread_mutex_unlock(uevq_lockp);
+       udev_unref(udev);
 }
 
 void
@@ -399,7 +401,7 @@ exit:
        return 1;
 }
 
-int uevent_listen(void)
+int uevent_listen(struct udev *udev)
 {
        int err;
        struct udev_monitor *monitor = NULL;
@@ -411,11 +413,17 @@ int uevent_listen(void)
         * thereby not getting to empty the socket's receive buffer queue
         * often enough.
         */
-       pthread_cleanup_push(uevq_stop, NULL);
+       if (!udev) {
+               condlog(1, "no udev context");
+               return 1;
+       }
+       udev_ref(udev);
+       pthread_cleanup_push(uevq_stop, udev);
 
-       monitor = udev_monitor_new_from_netlink(conf->udev, "udev");
+       monitor = udev_monitor_new_from_netlink(udev, "udev");
        if (!monitor) {
                condlog(2, "failed to create udev monitor");
+               err = 2;
                goto out;
        }
 #ifdef LIBUDEV_API_RECVBUF
index 762595a..e5fdfcc 100644 (file)
@@ -13,6 +13,8 @@
 #define NETLINK_KOBJECT_UEVENT         15
 #endif
 
+struct udev;
+
 struct uevent {
        struct list_head node;
        struct udev_device *udev;
@@ -27,7 +29,7 @@ struct uevent {
 int is_uevent_busy(void);
 void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
 
-int uevent_listen(void);
+int uevent_listen(struct udev *udev);
 int uevent_dispatch(int (*store_uev)(struct uevent *, void * trigger_data),
                    void * trigger_data);
 int uevent_get_major(struct uevent *uev);
index aa5a298..b41fc64 100644 (file)
@@ -835,7 +835,7 @@ out:
 static void *
 ueventloop (void * ap)
 {
-       if (uevent_listen())
+       if (uevent_listen(udev))
                condlog(0, "error starting uevent listener");
 
        return NULL;
@@ -1658,7 +1658,7 @@ child (void * param)
        /*
         * Start uevent listener early to catch events
         */
-       if ((rc = pthread_create(&uevent_thr, &misc_attr, ueventloop, vecs))) {
+       if ((rc = pthread_create(&uevent_thr, &misc_attr, ueventloop, udev))) {
                condlog(0, "failed to create uevent thread: %d", rc);
                exit(1);
        }