multipathd: Fix uxlsnr race condition on shutdown
authorHannes Reinecke <hare@suse.de>
Wed, 12 Jan 2011 09:13:04 +0000 (10:13 +0100)
committerHannes Reinecke <hare@suse.de>
Tue, 17 May 2011 12:36:45 +0000 (14:36 +0200)
The multipath daemon deallocates some memory structures
upon shutdown which have been allocated in the thread
context of uxlsnr. Upon shutdown this thread is already
done for, taking it's memory structures with it.
So we need to establish a proper pthread cleanup
handler here to ensure the memory structures are
freed correctly.

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

index b39a47f9ee8306e0a55fa5c1377962449e4de14a..7851a3ef7ec76044599fbe88bca3955e822373ae 100644 (file)
@@ -10,6 +10,9 @@
 
 #include "cli.h"
 
+static vector keys;
+static vector handlers;
+
 static struct key *
 alloc_key (void)
 {
@@ -124,15 +127,16 @@ free_keys (vector vec)
 }
 
 void
-free_handlers (vector vec)
+free_handlers (void)
 {
        int i;
        struct handler * h;
 
-       vector_foreach_slot (vec, h, i)
+       vector_foreach_slot (handlers, h, i)
                FREE(h);
 
-       vector_free(vec);
+       vector_free(handlers);
+       handlers = NULL;
 }
 
 int
@@ -448,6 +452,13 @@ cli_init (void) {
        return 0;
 }
 
+void cli_exit(void)
+{
+       free_handlers();
+       free_keys(keys);
+       keys = NULL;
+}
+
 static int
 key_match_fingerprint (struct key * kw, int fp)
 {
index 1a19e4ce92a400c24c4077ee9424d3b3f3d41750..41f4952f1e54e104dbfab634d41039cb94e6560a 100644 (file)
@@ -69,9 +69,6 @@ struct handler {
        int (*fn)(void *, char **, int *, void *);
 };
 
-vector keys;
-vector handlers;
-
 int alloc_handlers (void);
 int add_handler (int fp, int (*fn)(void *, char **, int *, void *));
 int set_handler_callback (int fp, int (*fn)(void *, char **, int *, void *));
@@ -79,6 +76,7 @@ int parse_cmd (char * cmd, char ** reply, int * len, void *);
 int load_keys (void);
 char * get_keyparam (vector v, int code);
 void free_keys (vector vec);
-void free_handlers (vector vec);
+void free_handlers (void);
 int cli_init (void);
+void cli_exit(void);
 char * key_generator (const char * str, int state);
index 1fcfb320927e771d08baf879659c46b01420ca4b..cdd33bd718742b70c83b90e6b30843c3f9330b6b 100644 (file)
@@ -1528,7 +1528,7 @@ child (void * param)
                vector_foreach_slot(vecs->mpvec, mpp, i)
                        dm_queue_if_no_path(mpp->alias, 0);
        remove_maps_and_stop_waiters(vecs);
-       free_pathvec(vecs->pathvec, FREE_PATHS);
+       unlock(vecs->lock);
 
        pthread_cancel(check_thr);
        pthread_cancel(uevent_thr);
@@ -1537,12 +1537,9 @@ child (void * param)
 
        sysfs_cleanup();
 
-       free_keys(keys);
-       keys = NULL;
-       free_handlers(handlers);
-       handlers = NULL;
-       free_polls();
-
+       lock(vecs->lock);
+       free_pathvec(vecs->pathvec, FREE_PATHS);
+       vecs->pathvec = NULL;
        unlock(vecs->lock);
        /* Now all the waitevent threads will start rushing in. */
        while (vecs->lock.depth > 0) {
index 679651c7ce40de475d1e33616bf12c6462d7e8b5..85dbd70c0a4cba3d587c6c3a2901a2c9715634d4 100644 (file)
@@ -29,6 +29,7 @@
 #include <uxsock.h>
 #include <defaults.h>
 
+#include "cli.h"
 #include "uxlsnr.h"
 
 #define SLEEP_TIME 5000
@@ -40,6 +41,7 @@ struct client {
 
 static struct client *clients;
 static unsigned num_clients;
+struct pollfd *polls;
 
 /*
  * handle a new client joining
@@ -81,7 +83,14 @@ static void dead_client(struct client *c)
 
 void free_polls (void)
 {
-       FREE(polls);
+       if (polls)
+               FREE(polls);
+}
+
+void uxsock_cleanup(void *arg)
+{
+       cli_exit();
+       free_polls();
 }
 
 /*
@@ -103,6 +112,8 @@ void * uxsock_listen(int (*uxsock_trigger)(char *, char **, int *, void *),
                exit(1);
        }
 
+       pthread_cleanup_push(uxsock_cleanup, NULL);
+
        polls = (struct pollfd *)MALLOC(0);
 
        while (1) {
@@ -129,7 +140,7 @@ void * uxsock_listen(int (*uxsock_trigger)(char *, char **, int *, void *),
 
                        /* something went badly wrong! */
                        condlog(0, "poll");
-                       exit(1);
+                       pthread_exit(NULL);
                }
 
                if (poll_count == 0)
@@ -169,6 +180,7 @@ void * uxsock_listen(int (*uxsock_trigger)(char *, char **, int *, void *),
                }
        }
 
+       pthread_cleanup_pop(1);
        close(ux_sock);
        return NULL;
 }
index 00d98b043eaf2cf05397ad76723a4bb4d79886b3..c646d5dd0180f914936584f078defc26ebf8edf4 100644 (file)
@@ -1,7 +1,8 @@
-struct pollfd *polls;
+#ifndef _UXLSNR_H
+#define _UXLSNR_H
 
-void free_polls(void);
 void * uxsock_listen(int (*uxsock_trigger)
                        (char *, char **, int *, void *),
                        void * trigger_data);
+#endif