device-mapper-multipath/0115-multipathd-add-code-to-initalize-unwinder.patch
DistroBaker 0a156fc43d Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/device-mapper-multipath.git#9fdf79cddf3be4e872b8d515e240dd533ea8dd34
2021-02-12 19:25:37 +00:00

135 lines
4.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 17 Dec 2020 16:50:06 +0100
Subject: [PATCH] multipathd: add code to initalize unwinder
glibc's implementation of pthread_cancel() loads symbols from
libgcc_s.so using dlopen() when pthread_cancel() is called
for the first time. This happens even with LD_BIND_NOW=1.
This may imply the need for file system access when a thread is
cancelled, which in the case of multipath-tools might be in a
dangerous situation where multipathd must avoid blocking.
Call load_unwinder() during startup to make sure the dynamic
linker has all necessary symbols resolved early on.
This implementation simply creates a dummy thread and cancels
it. This way all necessary symbols for thread cancellation
will be loaded, no matter what the C library needs to implement
cancellation.
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/Makefile | 2 +-
multipathd/init_unwinder.c | 34 ++++++++++++++++++++++++++++++++++
multipathd/init_unwinder.h | 21 +++++++++++++++++++++
multipathd/main.c | 2 ++
4 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 multipathd/init_unwinder.c
create mode 100644 multipathd/init_unwinder.h
diff --git a/multipathd/Makefile b/multipathd/Makefile
index 632b82b1..d053c1ed 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -30,7 +30,7 @@ ifeq ($(ENABLE_DMEVENTS_POLL),0)
endif
OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o \
- dmevents.o
+ dmevents.o init_unwinder.o
EXEC = multipathd
diff --git a/multipathd/init_unwinder.c b/multipathd/init_unwinder.c
new file mode 100644
index 00000000..14467f3d
--- /dev/null
+++ b/multipathd/init_unwinder.c
@@ -0,0 +1,34 @@
+#include <pthread.h>
+#include <unistd.h>
+#include "init_unwinder.h"
+
+static pthread_mutex_t dummy_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
+
+static void *dummy_thread(void *arg __attribute__((unused)))
+{
+ pthread_mutex_lock(&dummy_mtx);
+ pthread_cond_broadcast(&dummy_cond);
+ pthread_mutex_unlock(&dummy_mtx);
+ pause();
+ return NULL;
+}
+
+int init_unwinder(void)
+{
+ pthread_t dummy;
+ int rc;
+
+ pthread_mutex_lock(&dummy_mtx);
+
+ rc = pthread_create(&dummy, NULL, dummy_thread, NULL);
+ if (rc != 0) {
+ pthread_mutex_unlock(&dummy_mtx);
+ return rc;
+ }
+
+ pthread_cond_wait(&dummy_cond, &dummy_mtx);
+ pthread_mutex_unlock(&dummy_mtx);
+
+ return pthread_cancel(dummy);
+}
diff --git a/multipathd/init_unwinder.h b/multipathd/init_unwinder.h
new file mode 100644
index 00000000..ada09f82
--- /dev/null
+++ b/multipathd/init_unwinder.h
@@ -0,0 +1,21 @@
+#ifndef _INIT_UNWINDER_H
+#define _INIT_UNWINDER_H 1
+
+/*
+ * init_unwinder(): make sure unwinder symbols are loaded
+ *
+ * libc's implementation of pthread_cancel() loads symbols from
+ * libgcc_s.so using dlopen() when pthread_cancel() is called
+ * for the first time. This happens even with LD_BIND_NOW=1.
+ * This may imply the need for file system access when a thread is
+ * cancelled, which in the case of multipath-tools might be in a
+ * dangerous situation where multipathd must avoid blocking.
+ *
+ * Call load_unwinder() during startup to make sure the dynamic
+ * linker has all necessary symbols resolved early on.
+ *
+ * Return: 0 if successful, an error number otherwise.
+ */
+int init_unwinder(void);
+
+#endif
diff --git a/multipathd/main.c b/multipathd/main.c
index 99a89a69..6f851ae8 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -83,6 +83,7 @@
#include "wwids.h"
#include "foreign.h"
#include "../third-party/valgrind/drd.h"
+#include "init_unwinder.h"
#define FILE_NAME_SIZE 256
#define CMDSIZE 160
@@ -3041,6 +3042,7 @@ child (__attribute__((unused)) void *param)
enum daemon_status state;
int exit_code = 1;
+ init_unwinder();
mlockall(MCL_CURRENT | MCL_FUTURE);
signal_init();
mp_rcu_data = setup_rcu();
--
2.17.2