dll: fuse: improve signal handling under Cygwin

This commit is contained in:
Bill Zissimopoulos 2016-06-15 11:21:41 -07:00
parent 958f694b6f
commit b8ec5ba019
2 changed files with 84 additions and 21 deletions

View File

@ -173,6 +173,8 @@ struct fuse_flock
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
#include <fcntl.h> #include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/types.h> #include <sys/types.h>
@ -229,14 +231,27 @@ struct fsp_fuse_env
FSP_FUSE_API void fsp_fuse_signal_handler(int sig); FSP_FUSE_API void fsp_fuse_signal_handler(int sig);
FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se); FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se);
#if defined(_WIN64) || defined(_WIN32)
static inline int fsp_fuse_daemonize(int foreground) static inline int fsp_fuse_daemonize(int foreground)
{ {
#if defined(_WIN64) || defined(_WIN32)
(void)foreground; (void)foreground;
return 0; return 0;
}
static inline int fsp_fuse_set_signal_handlers(void *se)
{
(void)se;
return 0;
}
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
static inline int fsp_fuse_daemonize(int foreground)
{
int daemon(int nochdir, int noclose); int daemon(int nochdir, int noclose);
int chdir(const char *path); int chdir(const char *path);
if (!foreground) if (!foreground)
{ {
if (-1 == daemon(0, 0)) if (-1 == daemon(0, 0))
@ -244,38 +259,86 @@ static inline int fsp_fuse_daemonize(int foreground)
} }
else else
chdir("/"); chdir("/");
return 0;
}
static inline void *fsp_fuse_signal_thread(void *psigmask)
{
int sig;
if (0 == sigwait(psigmask, &sig))
fsp_fuse_signal_handler(sig);
return 0; return 0;
#endif
} }
static inline int fsp_fuse_set_signal_handlers(void *se) static inline int fsp_fuse_set_signal_handlers(void *se)
{ {
#if defined(_WIN64) || defined(_WIN32)
(void)se;
return 0;
#elif defined(__CYGWIN__)
#define FSP_FUSE_SET_SIGNAL_HANDLER(sig, newha)\ #define FSP_FUSE_SET_SIGNAL_HANDLER(sig, newha)\
newsa.sa_handler = se ? (newha) : SIG_DFL;\ if (-1 != sigaction((sig), 0, &oldsa) &&\
if (-1 == sigaction((sig), 0, &oldsa) ||\ oldsa.sa_handler == (se ? SIG_DFL : (newha)))\
(oldsa.sa_handler == (se ? SIG_DFL : (newha)) && -1 == sigaction((sig), &newsa, 0)))\ {\
return -1; newsa.sa_handler = se ? (newha) : SIG_DFL;\
sigaction((sig), &newsa, 0);\
}
#define FSP_FUSE_SIGADDSET(sig)\
if (-1 != sigaction((sig), 0, &oldsa) &&\
oldsa.sa_handler == SIG_DFL)\
sigaddset(&sigmask, (sig));
static sigset_t sigmask;
static pthread_t sigthr;
struct sigaction oldsa, newsa = { 0 }; struct sigaction oldsa, newsa = { 0 };
FSP_FUSE_SET_SIGNAL_HANDLER(SIGHUP, fsp_fuse_signal_handler); if (0 != se)
FSP_FUSE_SET_SIGNAL_HANDLER(SIGINT, fsp_fuse_signal_handler); {
FSP_FUSE_SET_SIGNAL_HANDLER(SIGTERM, fsp_fuse_signal_handler); if (0 == sigthr)
FSP_FUSE_SET_SIGNAL_HANDLER(SIGTERM, SIG_IGN); {
FSP_FUSE_SET_SIGNAL_HANDLER(SIGPIPE, SIG_IGN);
fsp_fuse_set_signal_arg(se); sigemptyset(&sigmask);
FSP_FUSE_SIGADDSET(SIGHUP);
FSP_FUSE_SIGADDSET(SIGINT);
FSP_FUSE_SIGADDSET(SIGTERM);
if (0 != pthread_sigmask(SIG_BLOCK, &sigmask, 0))
return -1;
fsp_fuse_set_signal_arg(se);
if (0 != pthread_create(&sigthr, 0, fsp_fuse_signal_thread, &sigmask))
{
fsp_fuse_set_signal_arg(0);
return -1;
}
}
}
else
{
if (0 != sigthr)
{
pthread_cancel(sigthr);
pthread_join(sigthr, 0);
sigthr = 0;
fsp_fuse_set_signal_arg(0);
if (0 != pthread_sigmask(SIG_UNBLOCK, &sigmask, 0))
return -1;
sigemptyset(&sigmask);
FSP_FUSE_SET_SIGNAL_HANDLER(SIGPIPE, SIG_IGN);
}
}
return 0; return 0;
#undef FSP_FUSE_SIGADDSET
#undef FSP_FUSE_SET_SIGNAL_HANDLER #undef FSP_FUSE_SET_SIGNAL_HANDLER
}
#endif #endif
}
static inline struct fsp_fuse_env *fsp_fuse_env(void) static inline struct fsp_fuse_env *fsp_fuse_env(void)
{ {

View File

@ -664,15 +664,15 @@ FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env,
/* Cygwin signal support */ /* Cygwin signal support */
static struct fuse *fsp_fuse_signal_arg; static FSP_SERVICE *fsp_fuse_signal_svc;
FSP_FUSE_API void fsp_fuse_signal_handler(int sig) FSP_FUSE_API void fsp_fuse_signal_handler(int sig)
{ {
if (0 != fsp_fuse_signal_arg && 0 != fsp_fuse_signal_arg->Service) if (0 != fsp_fuse_signal_svc)
FspServiceStop(fsp_fuse_signal_arg->Service); FspServiceStop(fsp_fuse_signal_svc);
} }
FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se) FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se)
{ {
fsp_fuse_signal_arg = se; fsp_fuse_signal_svc = 0 != se ? ((struct fuse *)se)->Service : 0;
} }