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