From: Hannes Reinecke Date: Tue, 16 Jul 2013 07:13:15 +0000 (+0200) Subject: multipath: reference the udev context when starting event queue X-Git-Tag: 0.5.0~61 X-Git-Url: https://git.opensvc.com/gitweb.cgi?p=multipath-tools%2F.git;a=commitdiff_plain;h=6c99cf739bb94e4172b98d1ff5458e588552bd0b multipath: reference the udev context when starting event queue 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 --- diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c index 0643e14e..9ee3ade6 100644 --- a/libmultipath/uevent.c +++ b/libmultipath/uevent.c @@ -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 diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h index 762595ac..e5fdfcc0 100644 --- a/libmultipath/uevent.h +++ b/libmultipath/uevent.h @@ -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); diff --git a/multipathd/main.c b/multipathd/main.c index aa5a298c..b41fc64f 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -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); }