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 b39a47f..7851a3e 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 1a19e4c..41f4952 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 1fcfb32..cdd33bd 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 679651c..85dbd70 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 00d98b0..c646d5d 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