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