From 230cbdb4e1dcb2351398bbc8b6f40fc6ba88d40a Mon Sep 17 00:00:00 2001 From: alexpeshkoff Date: Fri, 10 Aug 2007 13:55:41 +0000 Subject: [PATCH] Made classes SignalInhibit and AstInhibit async signal safe. --- src/jrd/os/isc_i_proto.h | 5 +++-- src/jrd/os/posix/isc_ipc.cpp | 42 +++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/jrd/os/isc_i_proto.h b/src/jrd/os/isc_i_proto.h index c74b7501db..b65a167f71 100644 --- a/src/jrd/os/isc_i_proto.h +++ b/src/jrd/os/isc_i_proto.h @@ -68,10 +68,11 @@ public: void enable() throw() { } #endif private: - // Forbid copy constructor + // Forbid copy constructor & assignment SignalInhibit(const SignalInhibit&); + SignalInhibit& operator=(const SignalInhibit&); #ifndef WIN_NT - bool enabled; + bool locked; #endif }; diff --git a/src/jrd/os/posix/isc_ipc.cpp b/src/jrd/os/posix/isc_ipc.cpp index b9113a38c7..2c9da88c14 100644 --- a/src/jrd/os/posix/isc_ipc.cpp +++ b/src/jrd/os/posix/isc_ipc.cpp @@ -166,39 +166,44 @@ void ISC_enter(void) } namespace { - volatile sig_atomic_t inhibit_counter = 0; - sigset_t saved_sigmask; + volatile int inhibitCounter = 0; Firebird::Mutex inhibitMutex; + sigset_t savedSigmask; + volatile bool inSignalHandler = false; } SignalInhibit::SignalInhibit() throw() - : enabled(false) + : locked(!inSignalHandler) // When called from signal handler, no need + // to care - signals are already inhibited. { + if (!locked) + return; + Firebird::MutexLockGuard lock(inhibitMutex); - if (inhibit_counter == 0) { - sigset_t set, oset; + if (inhibitCounter == 0) { + sigset_t set; sigfillset(&set); - sigprocmask(SIG_BLOCK, &set, &saved_sigmask); + sigprocmask(SIG_BLOCK, &set, &savedSigmask); } - inhibit_counter++; + inhibitCounter++; } void SignalInhibit::enable() throw() { - if (enabled) + if (!locked) return; - enabled = true; + locked = false; Firebird::MutexLockGuard lock(inhibitMutex); - fb_assert(inhibit_counter > 0); - inhibit_counter--; - if (inhibit_counter == 0) { + fb_assert(inhibitCounter > 0); + inhibitCounter--; + if (inhibitCounter == 0) { // Return to the mask as it were before the first recursive // call to ISC_inhibit - sigprocmask(SIG_SETMASK, &saved_sigmask, NULL); + sigprocmask(SIG_SETMASK, &savedSigmask, NULL); } } @@ -562,6 +567,13 @@ static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *con **************************************/ /* Invoke everybody who may have expressed an interest. */ + bool restoreState = inSignalHandler; + inSignalHandler = true; + + sigset_t set, localSavedSigmask; + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, &localSavedSigmask); + for (SIG sig = signals; sig; sig = sig->sig_next) { if (sig->sig_signal == number) @@ -591,5 +603,9 @@ static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *con } } } + + sigprocmask(SIG_SETMASK, &localSavedSigmask, NULL); + + inSignalHandler = restoreState; }