Blame SOURCES/0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch

05be62
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
05be62
From: Benjamin Marzinski <bmarzins@redhat.com>
05be62
Date: Fri, 23 Oct 2020 11:38:24 -0500
05be62
Subject: [PATCH] libmultipath: don't dlclose tur checker DSO
05be62
05be62
The multipathd tur checker thread is designed to be able to finish at
05be62
any time, even after the tur checker itself has been freed. The
05be62
multipathd shutdown code makes sure all the checkers have been freed
05be62
before freeing the checker_class and calling dlclose() to unload the
05be62
DSO, but this doesn't guarantee that the checker threads have finished.
05be62
If one hasn't, the DSO will get unloaded while the thread still running
05be62
code from it, causing a segfault. Unfortunately, it's not possible to be
05be62
sure that all tur checker threads have ended during shutdown, without
05be62
making them joinable.
05be62
05be62
However, since libmultipath will never be reinitialized after it has
05be62
been uninitialzed, not dlclosing the tur checker DSO once a thread is
05be62
started has minimal cost (keeping the DSO code around until the program
05be62
exits, which usually happens right after freeing the checkers).
05be62
05be62
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
05be62
---
05be62
 libmultipath/checkers.c     | 10 +++++++++-
05be62
 libmultipath/checkers.h     |  1 +
05be62
 libmultipath/checkers/tur.c |  1 +
05be62
 3 files changed, 11 insertions(+), 1 deletion(-)
05be62
05be62
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
05be62
index 8d2be8a9..6359e5d8 100644
05be62
--- a/libmultipath/checkers.c
05be62
+++ b/libmultipath/checkers.c
05be62
@@ -21,6 +21,7 @@ struct checker_class {
05be62
 	void (*reset)(void);		     /* to reset the global variables */
05be62
 	const char **msgtable;
05be62
 	short msgtable_size;
05be62
+	int keep_dso;
05be62
 };
05be62
 
05be62
 char *checker_state_names[] = {
05be62
@@ -69,7 +70,7 @@ void free_checker_class(struct checker_class *c)
05be62
 	list_del(&c->node);
05be62
 	if (c->reset)
05be62
 		c->reset();
05be62
-	if (c->handle) {
05be62
+	if (c->handle && !c->keep_dso) {
05be62
 		if (dlclose(c->handle) != 0) {
05be62
 			condlog(0, "Cannot unload checker %s: %s",
05be62
 				c->name, dlerror());
05be62
@@ -192,6 +193,13 @@ out:
05be62
 	return NULL;
05be62
 }
05be62
 
05be62
+void checker_keep_dso(struct checker * c)
05be62
+{
05be62
+	if (!c || !c->cls)
05be62
+		return;
05be62
+	c->cls->keep_dso = 1;
05be62
+}
05be62
+
05be62
 void checker_set_fd (struct checker * c, int fd)
05be62
 {
05be62
 	if (!c)
05be62
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
05be62
index b458118d..f183cff9 100644
05be62
--- a/libmultipath/checkers.h
05be62
+++ b/libmultipath/checkers.h
05be62
@@ -145,6 +145,7 @@ void checker_reset (struct checker *);
05be62
 void checker_set_sync (struct checker *);
05be62
 void checker_set_async (struct checker *);
05be62
 void checker_set_fd (struct checker *, int);
05be62
+void checker_keep_dso(struct checker *c);
05be62
 void checker_enable (struct checker *);
05be62
 void checker_disable (struct checker *);
05be62
 int checker_check (struct checker *, int);
05be62
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
05be62
index e886fcf8..fd58d62a 100644
05be62
--- a/libmultipath/checkers/tur.c
05be62
+++ b/libmultipath/checkers/tur.c
05be62
@@ -394,6 +394,7 @@ int libcheck_check(struct checker * c)
05be62
 		uatomic_set(&ct->running, 1);
05be62
 		tur_set_async_timeout(c);
05be62
 		setup_thread_attr(&attr, 32 * 1024, 1);
05be62
+		checker_keep_dso(c);
05be62
 		r = pthread_create(&ct->thread, &attr, tur_thread, ct);
05be62
 		pthread_attr_destroy(&attr);
05be62
 		if (r) {
05be62
-- 
05be62
2.17.2
05be62