diff options
author | Bernd Schubert <bschubert@ddn.com> | 2025-03-30 22:43:09 +0200 |
---|---|---|
committer | Bernd Schubert <bernd@bsbernd.com> | 2025-04-24 16:10:40 +0200 |
commit | c5dbcdce2d1942abb567d03bf9dafb74f06b5769 (patch) | |
tree | 9bf54e908b73c2acae3b326c930a1e243c354dad /lib/fuse_lowlevel.c | |
parent | e025a78d9b296bc78e9e3ac2925d8bc0ec26d702 (diff) | |
download | libfuse-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.c | 18 |
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; } |