aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fuse_lowlevel.c
diff options
context:
space:
mode:
authorBernd Schubert <bschubert@ddn.com>2025-03-30 22:43:09 +0200
committerBernd Schubert <bernd@bsbernd.com>2025-04-24 16:10:40 +0200
commitc5dbcdce2d1942abb567d03bf9dafb74f06b5769 (patch)
tree9bf54e908b73c2acae3b326c930a1e243c354dad /lib/fuse_lowlevel.c
parente025a78d9b296bc78e9e3ac2925d8bc0ec26d702 (diff)
downloadlibfuse-c5dbcdce2d1942abb567d03bf9dafb74f06b5769.tar.gz
Fix multi-threaded fuse session exit
Issue with previous code was that fuse_session_exit() didn't wake up the semaphore in fuse_loop_mt.c. Lock, semaphore and all uses of checking for "exited" are now moved to struct fuse_session to have it available for the signal handler. This also removes internal fuse_session_reset() calls, as that makes testing hard. From git history I also don't see why it was added. Closes: https://github.com/libfuse/libfuse/issues/997 Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r--lib/fuse_lowlevel.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index cf8a7b0..d66e6ab 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -19,6 +19,8 @@
#include "mount_util.h"
#include "util.h"
+#include <pthread.h>
+#include <stdatomic.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
@@ -3006,6 +3008,8 @@ void fuse_session_destroy(struct fuse_session *se)
if (llp != NULL)
fuse_ll_pipe_free(llp);
pthread_key_delete(se->pipe_key);
+ sem_destroy(&se->mt_finish);
+ pthread_mutex_destroy(&se->mt_lock);
pthread_mutex_destroy(&se->lock);
free(se->cuse_data);
if (se->fd != -1)
@@ -3358,6 +3362,8 @@ fuse_session_new_versioned(struct fuse_args *args,
list_init_nreq(&se->notify_list);
se->notify_ctr = 1;
pthread_mutex_init(&se->lock, NULL);
+ sem_init(&se->mt_finish, 0, 0);
+ pthread_mutex_init(&se->mt_lock, NULL);
err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor);
if (err) {
@@ -3382,6 +3388,8 @@ fuse_session_new_versioned(struct fuse_args *args,
return se;
out5:
+ sem_destroy(&se->mt_finish);
+ pthread_mutex_destroy(&se->mt_lock);
pthread_mutex_destroy(&se->lock);
out4:
fuse_opt_free_args(args);
@@ -3605,18 +3613,22 @@ int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
__attribute__((no_sanitize_thread))
void fuse_session_exit(struct fuse_session *se)
{
- se->exited = 1;
+ atomic_store_explicit(&se->mt_exited, 1, memory_order_relaxed);
+ sem_post(&se->mt_finish);
}
__attribute__((no_sanitize_thread))
void fuse_session_reset(struct fuse_session *se)
{
- se->exited = 0;
+ se->mt_exited = false;
se->error = 0;
}
__attribute__((no_sanitize_thread))
int fuse_session_exited(struct fuse_session *se)
{
- return se->exited;
+ bool exited =
+ atomic_load_explicit(&se->mt_exited, memory_order_relaxed);
+
+ return exited ? 1 : 0;
}