8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 15:23:02 +01:00

Backported fix for CORE-2049: Performance regression - too many sigprocmask() system calls

This commit is contained in:
alexpeshkoff 2008-08-22 13:17:55 +00:00
parent b5fc5afa80
commit edc71f54ae
2 changed files with 53 additions and 22 deletions

View File

@ -67,10 +67,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

@ -36,7 +36,7 @@
* *
*/ */
/* $Id: isc_ipc.cpp,v 1.17.4.3 2008-06-27 11:28:48 alexpeshkoff Exp $ */ /* $Id: isc_ipc.cpp,v 1.17.4.4 2008-08-22 13:17:55 alexpeshkoff Exp $ */
#include "firebird.h" #include "firebird.h"
#include <stdio.h> #include <stdio.h>
@ -168,42 +168,48 @@ void ISC_enter(void)
} }
namespace { namespace {
volatile sig_atomic_t inhibit_counter = 0; volatile sig_atomic_t inhibitCounter = 0;
sigset_t saved_sigmask;
Firebird::Mutex inhibitMutex; Firebird::Mutex inhibitMutex;
volatile bool inSignalHandler = false;
volatile FB_UINT64 pendingSignals = 0;
} }
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) { ++inhibitCounter;
sigset_t set, oset;
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &saved_sigmask);
}
inhibit_counter++;
} }
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--; if (--inhibitCounter == 0) {
if (inhibit_counter == 0) { while (pendingSignals)
// Return to the mask as it were before the first recursive {
// call to ISC_inhibit for (int n = 0; pendingSignals && n < 64; n++)
sigprocmask(SIG_SETMASK, &saved_sigmask, NULL); {
if (pendingSignals & (1 << n))
{
pendingSignals &= ~(1 << n);
ISC_kill(process_id, n + 1);
}
}
}
} }
} }
void ISC_exit(void) void ISC_exit(void)
@ -461,6 +467,10 @@ static void cleanup(void* arg)
**************************************/ **************************************/
signals = NULL; signals = NULL;
pendingSignals = 0;
inhibitCounter = 0;
process_id = 0; process_id = 0;
initialized_signals = false; initialized_signals = false;
@ -558,6 +568,21 @@ static void CLIB_ROUTINE signal_handler(int number)
* Checkin with various signal handlers. * Checkin with various signal handlers.
* *
**************************************/ **************************************/
if (inhibitCounter > 0 && number != SIGALRM)
{
pendingSignals |= QUADCONST(1) << (number - 1);
return;
}
#ifndef SUPERSERVER
// Save signal delivery status.
const bool restoreState = inSignalHandler;
inSignalHandler = true;
sigset_t set, localSavedSigmask;
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &localSavedSigmask);
#endif
/* Invoke everybody who may have expressed an interest. */ /* Invoke everybody who may have expressed an interest. */
for (SIG sig = signals; sig; sig = sig->sig_next) for (SIG sig = signals; sig; sig = sig->sig_next)
@ -571,5 +596,10 @@ static void CLIB_ROUTINE signal_handler(int number)
} }
else else
(*sig->sig_routine.user) (sig->sig_arg); (*sig->sig_routine.user) (sig->sig_arg);
#ifndef SUPERSERVER
sigprocmask(SIG_SETMASK, &localSavedSigmask, NULL);
inSignalHandler = restoreState;
#endif
} }