libfuse: use atomic fuse_session pointer in signal handler

The signal handler reads the global session pointer from an async-
signal context while another thread installs/removes the session
via set/remove_signal_handlers. Use std::atomic<fuse_session*> with
acquire/release ordering so the handler either sees NULL or a fully
published session, never a torn pointer.
This commit is contained in:
Antonio S. Musumeci
2026-04-18 13:47:23 -05:00
committed by trapexit
parent 4516685ca7
commit 27acd9fcc7
+15 -10
View File
@@ -8,19 +8,24 @@
#include "fuse_lowlevel.h"
#include <atomic>
#include <stdio.h>
#include <string.h>
#include <signal.h>
static struct fuse_session *fuse_instance;
static std::atomic<fuse_session*> g_fuse_instance{nullptr};
static
void
exit_handler(int sig)
{
(void)sig;
if (fuse_instance)
fuse_session_exit(fuse_instance);
struct fuse_session *instance;
instance = g_fuse_instance.load(std::memory_order_acquire);
if(instance)
fuse_session_exit(instance);
}
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
@@ -54,20 +59,20 @@ int fuse_set_signal_handlers(struct fuse_session *se)
(set_one_signal_handler(SIGPIPE, SIG_IGN, 0) == -1))
return -1;
fuse_instance = se;
g_fuse_instance.store(se,std::memory_order_release);
return 0;
}
void fuse_remove_signal_handlers(struct fuse_session *se)
{
if (fuse_instance != se)
fprintf(stderr,
"fuse: fuse_remove_signal_handlers: unknown session\n");
else
fuse_instance = NULL;
set_one_signal_handler(SIGINT, exit_handler, 1);
set_one_signal_handler(SIGTERM, exit_handler, 1);
set_one_signal_handler(SIGQUIT, exit_handler, 1);
set_one_signal_handler(SIGPIPE, SIG_IGN, 1);
if(g_fuse_instance.load(std::memory_order_acquire) != se)
fprintf(stderr,"mergerfs: fuse_remove_signal_handlers: unknown session\n");
else
g_fuse_instance.store(nullptr,std::memory_order_release);
}