device-mapper-multipath/0056-libmultipath-fix-log_thread-startup-and-teardown.patch
DistroBaker 28d3ae407e 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#26a2cd7a3e189bf91263d17bc8a8c449cc043fb0
2021-01-21 16:56:27 +00:00

149 lines
4.1 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 26 Oct 2020 16:44:32 +0100
Subject: [PATCH] libmultipath: fix log_thread startup and teardown
This fixes several issues with the log_thread. First, the running flag
logq_running should be set by the thread itself, not by
log_thread_start()/_stop(). Second, the thread was both cancelled and
terminated via a flag (again, logq_running). It's sufficient to just cancel
and join it. Third, the locking wasn't cancel-safe in some places. Forth,
log_thread_start() didn't wait for startup properly. Fifth, using (pthread_t)0
is wrong (pthread_t is opaque; there's no guarantee that 0 is not a valid
pthread_t value). Sixth, pthread_cancel() was called under logq_lock, which
doesn't make sense to me.
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/log_pthread.c | 62 +++++++++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 17 deletions(-)
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
index 0c327ffc..3a2566ae 100644
--- a/libmultipath/log_pthread.c
+++ b/libmultipath/log_pthread.c
@@ -13,6 +13,7 @@
#include "log_pthread.h"
#include "log.h"
#include "lock.h"
+#include "util.h"
static pthread_t log_thr;
@@ -56,35 +57,52 @@ static void flush_logqueue (void)
} while (empty == 0);
}
+static void cleanup_log_thread(__attribute((unused)) void *arg)
+{
+ logdbg(stderr, "log thread exiting");
+ pthread_mutex_lock(&logev_lock);
+ logq_running = 0;
+ pthread_mutex_unlock(&logev_lock);
+}
+
static void * log_thread (__attribute__((unused)) void * et)
{
int running;
pthread_mutex_lock(&logev_lock);
- logq_running = 1;
+ running = logq_running;
+ if (!running)
+ logq_running = 1;
+ pthread_cond_signal(&logev_cond);
pthread_mutex_unlock(&logev_lock);
+ if (running)
+ /* already started */
+ return NULL;
+ pthread_cleanup_push(cleanup_log_thread, NULL);
mlockall(MCL_CURRENT | MCL_FUTURE);
logdbg(stderr,"enter log_thread\n");
while (1) {
pthread_mutex_lock(&logev_lock);
- if (logq_running && !log_messages_pending)
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
+ while (!log_messages_pending)
+ /* this is a cancellation point */
pthread_cond_wait(&logev_cond, &logev_lock);
log_messages_pending = 0;
- running = logq_running;
- pthread_mutex_unlock(&logev_lock);
- if (!running)
- break;
+ pthread_cleanup_pop(1);
+
flush_logqueue();
}
+ pthread_cleanup_pop(1);
return NULL;
}
void log_thread_start (pthread_attr_t *attr)
{
- logdbg(stderr,"enter log_thread_start\n");
+ int running = 0;
+ logdbg(stderr,"enter log_thread_start\n");
pthread_mutex_init(&logq_lock, NULL);
pthread_mutex_init(&logev_lock, NULL);
pthread_cond_init(&logev_cond, NULL);
@@ -93,7 +111,15 @@ void log_thread_start (pthread_attr_t *attr)
fprintf(stderr,"can't initialize log buffer\n");
exit(1);
}
- if (pthread_create(&log_thr, attr, log_thread, NULL)) {
+
+ pthread_mutex_lock(&logev_lock);
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
+ if (!pthread_create(&log_thr, attr, log_thread, NULL))
+ while (!(running = logq_running))
+ pthread_cond_wait(&logev_cond, &logev_lock);
+ pthread_cleanup_pop(1);
+
+ if (!running) {
fprintf(stderr,"can't start log thread\n");
exit(1);
}
@@ -112,23 +138,25 @@ void log_thread_reset (void)
void log_thread_stop (void)
{
+ int running;
+
if (!la)
return;
logdbg(stderr,"enter log_thread_stop\n");
pthread_mutex_lock(&logev_lock);
- logq_running = 0;
- pthread_cond_signal(&logev_cond);
- pthread_mutex_unlock(&logev_lock);
-
- pthread_mutex_lock(&logq_lock);
- pthread_cancel(log_thr);
- pthread_mutex_unlock(&logq_lock);
- pthread_join(log_thr, NULL);
- log_thr = (pthread_t)0;
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
+ running = logq_running;
+ if (running) {
+ pthread_cancel(log_thr);
+ pthread_cond_signal(&logev_cond);
+ }
+ pthread_cleanup_pop(1);
flush_logqueue();
+ if (running)
+ pthread_join(log_thr, NULL);
pthread_mutex_destroy(&logq_lock);
pthread_mutex_destroy(&logev_lock);
--
2.17.2