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:
parent
b5fc5afa80
commit
edc71f54ae
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user