8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 00:03:03 +01:00

Made classes SignalInhibit and AstInhibit async signal safe.

This commit is contained in:
alexpeshkoff 2007-08-10 13:55:41 +00:00
parent 935b1251da
commit 230cbdb4e1
2 changed files with 32 additions and 15 deletions

View File

@ -68,10 +68,11 @@ public:
void enable() throw() { } void enable() throw() { }
#endif #endif
private: private:
// Forbid copy constructor // Forbid copy constructor & assignment
SignalInhibit(const SignalInhibit&); SignalInhibit(const SignalInhibit&);
SignalInhibit& operator=(const SignalInhibit&);
#ifndef WIN_NT #ifndef WIN_NT
bool enabled; bool locked;
#endif #endif
}; };

View File

@ -166,39 +166,44 @@ void ISC_enter(void)
} }
namespace { namespace {
volatile sig_atomic_t inhibit_counter = 0; volatile int inhibitCounter = 0;
sigset_t saved_sigmask;
Firebird::Mutex inhibitMutex; Firebird::Mutex inhibitMutex;
sigset_t savedSigmask;
volatile bool inSignalHandler = false;
} }
SignalInhibit::SignalInhibit() throw() 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); Firebird::MutexLockGuard lock(inhibitMutex);
if (inhibit_counter == 0) { if (inhibitCounter == 0) {
sigset_t set, oset; sigset_t set;
sigfillset(&set); sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &saved_sigmask); sigprocmask(SIG_BLOCK, &set, &savedSigmask);
} }
inhibit_counter++; inhibitCounter++;
} }
void SignalInhibit::enable() throw() void SignalInhibit::enable() throw()
{ {
if (enabled) if (!locked)
return; return;
enabled = true; locked = false;
Firebird::MutexLockGuard lock(inhibitMutex); Firebird::MutexLockGuard lock(inhibitMutex);
fb_assert(inhibit_counter > 0); fb_assert(inhibitCounter > 0);
inhibit_counter--; inhibitCounter--;
if (inhibit_counter == 0) { if (inhibitCounter == 0) {
// Return to the mask as it were before the first recursive // Return to the mask as it were before the first recursive
// call to ISC_inhibit // 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. */ /* 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) for (SIG sig = signals; sig; sig = sig->sig_next)
{ {
if (sig->sig_signal == number) 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;
} }