mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Frontported fix for CORE-3589: Internal shared resource leak. Make trunk work with SystemV semaphores as shared mutexes/events.
This commit is contained in:
parent
8ee9033501
commit
9dab626467
@ -63,6 +63,7 @@
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/StatusArg.h"
|
||||
#include "../common/ThreadData.h"
|
||||
|
||||
#ifdef UNIX
|
||||
#include <setjmp.h>
|
||||
@ -94,8 +95,7 @@ static int process_id;
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include "../common/classes/semaphore.h"
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
@ -136,6 +136,7 @@ static size_t getpagesize()
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define DEBUG_IPC
|
||||
#ifdef DEBUG_IPC
|
||||
#define IPC_TRACE(x) { /*time_t t; time(&t); printf("%s", ctime(&t) ); printf x; fflush (stdout);*/ gds__log x; }
|
||||
#else
|
||||
@ -306,6 +307,9 @@ namespace {
|
||||
|
||||
#ifdef USE_SYS5SEMAPHORE
|
||||
|
||||
// Uncomment to trace details of event_init/fini calls
|
||||
//#define DEB_EVNT
|
||||
|
||||
static SLONG create_semaphores(Arg::StatusVector&, SLONG, int);
|
||||
|
||||
namespace {
|
||||
@ -447,6 +451,7 @@ namespace {
|
||||
|
||||
if (n >= N_SETS)
|
||||
{
|
||||
fb_assert(false); // Not supposed to overflow
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -526,6 +531,37 @@ namespace {
|
||||
return n >= 0 ? &sharedFiles[n] : 0;
|
||||
}
|
||||
|
||||
#ifdef DEB_EVNT
|
||||
struct AbsPtr
|
||||
{
|
||||
SLONG offset;
|
||||
int fn;
|
||||
bool bad()
|
||||
{
|
||||
return offset < 0 || fn < 0;
|
||||
}
|
||||
AbsPtr()
|
||||
: offset(-1), fn(-1)
|
||||
{ }
|
||||
bool operator==(const AbsPtr& sec) const
|
||||
{
|
||||
return offset == sec.offset && fn == sec.fn;
|
||||
}
|
||||
};
|
||||
|
||||
static AbsPtr absPtr(const void* s)
|
||||
{
|
||||
const int n = getByAddress((UCHAR*) s);
|
||||
AbsPtr rc;
|
||||
if (n >= 0)
|
||||
{
|
||||
rc.offset = (IPTR)s - (IPTR)(sharedFiles[n].from);
|
||||
rc.fn = sharedFiles[n].fileNum;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif // DEB_EVNT
|
||||
|
||||
static void push(const SharedFile& sf)
|
||||
{
|
||||
MutexLockGuard guard(mutex);
|
||||
@ -628,6 +664,7 @@ namespace {
|
||||
{
|
||||
semctl(id, 0, IPC_RMID);
|
||||
}
|
||||
set[n].fileNum = -1;
|
||||
}
|
||||
idCache[n] = -1;
|
||||
}
|
||||
@ -641,16 +678,26 @@ namespace {
|
||||
// Lock init file.
|
||||
FileLock initLock(status, fd_init, FileLock::OPENED);
|
||||
if (!initLock.exclusive())
|
||||
{
|
||||
iscLogStatus("initLock.exclusive() failed", status.value());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find out what file does it belong to.
|
||||
SharedFile* sf = SharedFile::locate(sem);
|
||||
if (!sf)
|
||||
{
|
||||
gds__log("SharedFile::locate(sem) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return semTable->get(sf->getNum(), sem);
|
||||
if (!semTable->get(sf->getNum(), sem))
|
||||
{
|
||||
gds__log("semTable->get() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void freeSem5(Sys5Semaphore* sem)
|
||||
@ -667,6 +714,92 @@ namespace {
|
||||
|
||||
semTable->put(sem);
|
||||
}
|
||||
|
||||
#ifdef DEB_EVNT
|
||||
|
||||
struct Dump
|
||||
{
|
||||
SharedFile::AbsPtr e;
|
||||
enum
|
||||
{
|
||||
WORKING, INIT, FINI, INIT_ERR
|
||||
} state;
|
||||
int code;
|
||||
};
|
||||
GlobalPtr<Array<Dump> > dump;
|
||||
GlobalPtr<Mutex> dMutex;
|
||||
|
||||
Dump* dFind(const event_t* ev)
|
||||
{
|
||||
SharedFile::AbsPtr e = SharedFile::absPtr(ev);
|
||||
fb_assert(!e.bad());
|
||||
for (Dump* itr = dump->begin(); itr < dump->end(); ++itr)
|
||||
{
|
||||
if (itr->e == e)
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void initStart(const event_t* e)
|
||||
{
|
||||
MutexLockGuard g(dMutex);
|
||||
Dump* d = dFind(e);
|
||||
if (d)
|
||||
{
|
||||
fb_assert(d->state == Dump::INIT_ERR);
|
||||
d->state = Dump::INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
Dump dd;
|
||||
dd.e = SharedFile::absPtr(e);
|
||||
fb_assert(!dd.e.bad());
|
||||
dd.state = Dump::INIT;
|
||||
dd.code = 0;
|
||||
dump->add(dd);
|
||||
}
|
||||
}
|
||||
|
||||
void initStop(const event_t* e, int code)
|
||||
{
|
||||
MutexLockGuard g(dMutex);
|
||||
Dump* d = dFind(e);
|
||||
|
||||
fb_assert(d && (d->state == Dump::INIT));
|
||||
d->state = code ? Dump::INIT_ERR : Dump::WORKING;
|
||||
d->code = code;
|
||||
}
|
||||
|
||||
void finiStart(const event_t* e)
|
||||
{
|
||||
MutexLockGuard g(dMutex);
|
||||
Dump* d = dFind(e);
|
||||
|
||||
fb_assert(d && (d->state == Dump::WORKING));
|
||||
d->state = Dump::FINI;
|
||||
}
|
||||
|
||||
void finiStop(const event_t* e)
|
||||
{
|
||||
MutexLockGuard g(dMutex);
|
||||
Dump* d = dFind(e);
|
||||
|
||||
fb_assert(d && (d->state == Dump::FINI));
|
||||
dump->remove(d);
|
||||
}
|
||||
|
||||
#else // DEB_EVNT
|
||||
|
||||
void initStart(const event_t* event) {}
|
||||
void initStop(const event_t* event, int code) {}
|
||||
void finiStart(const event_t* event) {}
|
||||
void finiStop(const event_t* event) {}
|
||||
|
||||
#endif // DEB_EVNT
|
||||
|
||||
}
|
||||
|
||||
int Sys5Semaphore::getId()
|
||||
@ -741,43 +874,89 @@ static bool event_blocked(const event_t* event, const SLONG value)
|
||||
|
||||
namespace {
|
||||
|
||||
GlobalPtr<Mutex> timerAccess;
|
||||
GlobalPtr<Semaphore> timerWakeup, timerFini;
|
||||
|
||||
void stopTimers(void*);
|
||||
bool stopThread = false;
|
||||
|
||||
struct TimerEntry
|
||||
class TimerEntry : public Firebird::RefCntIface<Firebird::ITimer, FB_TIMER_VERSION>
|
||||
{
|
||||
SINT64 fireTime;
|
||||
public:
|
||||
TimerEntry(int id, USHORT num)
|
||||
: semId(id), semNum(num)
|
||||
{ }
|
||||
|
||||
void FB_CARG handler()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
union semun arg;
|
||||
arg.val = 0;
|
||||
int ret = semctl(semId, semNum, SETVAL, arg);
|
||||
if (ret != -1)
|
||||
break;
|
||||
if (!SYSCALL_INTERRUPTED(errno))
|
||||
{
|
||||
gds__log("semctl() failed, errno %d\n", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FB_CARG release()
|
||||
{
|
||||
if (--refCounter == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool operator== (Sys5Semaphore& sem)
|
||||
{
|
||||
return semId == sem.getId() && semNum == sem.semNum;
|
||||
}
|
||||
|
||||
private:
|
||||
int semId;
|
||||
USHORT semNum;
|
||||
|
||||
static const SINT64& generate(const void* /*sender*/, const TimerEntry& item) { return item.fireTime; }
|
||||
static THREAD_ENTRY_DECLARE timeThread(THREAD_ENTRY_PARAM);
|
||||
|
||||
static void init()
|
||||
{
|
||||
int rc = gds__thread_start(timeThread, 0, 0, 0, 0);
|
||||
if (rc != 0)
|
||||
{
|
||||
fatal_exception::raiseFmt("Error starting timer thread");
|
||||
}
|
||||
gds__register_cleanup(stopTimers, 0);
|
||||
}
|
||||
|
||||
static void cleanup()
|
||||
{
|
||||
stopThread = true;
|
||||
timerWakeup->release();
|
||||
timerFini->enter();
|
||||
}
|
||||
};
|
||||
|
||||
typedef SortedArray<TimerEntry, InlineStorage<TimerEntry, 64>, SINT64, TimerEntry> TimerQueue;
|
||||
typedef HalfStaticArray<TimerEntry*, 64> TimerQueue;
|
||||
GlobalPtr<TimerQueue> timerQueue;
|
||||
GlobalPtr<Mutex> timerAccess;
|
||||
|
||||
InitMutex<TimerEntry> timerHolder;
|
||||
void addTimer(Sys5Semaphore* sem, int microSeconds)
|
||||
{
|
||||
TimerEntry* newTimer = new TimerEntry(sem->getId(), sem->semNum);
|
||||
{
|
||||
MutexLockGuard guard(timerAccess);
|
||||
timerQueue->push(newTimer);
|
||||
}
|
||||
TimerInterfacePtr()->start(newTimer, microSeconds);
|
||||
}
|
||||
|
||||
void delTimer(Sys5Semaphore* sem)
|
||||
{
|
||||
bool found = false;
|
||||
TimerEntry** t;
|
||||
|
||||
{
|
||||
MutexLockGuard guard(timerAccess);
|
||||
|
||||
for (t = timerQueue->begin(); t < timerQueue->end(); ++t)
|
||||
{
|
||||
if (**t == *sem)
|
||||
{
|
||||
timerQueue->remove(t);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
TimerInterfacePtr()->stop(*t);
|
||||
}
|
||||
}
|
||||
|
||||
SINT64 curTime()
|
||||
{
|
||||
@ -789,97 +968,8 @@ SINT64 curTime()
|
||||
system_call_failed::raise("gettimeofday");
|
||||
}
|
||||
|
||||
SINT64 timeout = ((SINT64) cur_time.tv_sec) * 1000000 + cur_time.tv_usec;
|
||||
return timeout;
|
||||
}
|
||||
|
||||
SINT64 addTimer(Sys5Semaphore* sem, int microSeconds)
|
||||
{
|
||||
timerHolder.init();
|
||||
|
||||
TimerEntry newTimer;
|
||||
newTimer.fireTime = curTime() + microSeconds;
|
||||
newTimer.semId = sem->getId();
|
||||
newTimer.semNum = sem->semNum;
|
||||
|
||||
MutexLockGuard guard(timerAccess);
|
||||
|
||||
timerQueue->add(newTimer);
|
||||
timerWakeup->release();
|
||||
|
||||
return newTimer.fireTime;
|
||||
}
|
||||
|
||||
void delTimer(Sys5Semaphore* sem)
|
||||
{
|
||||
const int id = sem->getId();
|
||||
|
||||
MutexLockGuard guard(timerAccess);
|
||||
|
||||
for (unsigned int i = 0; i < timerQueue->getCount(); ++i)
|
||||
{
|
||||
const TimerEntry& e(timerQueue->operator[](i));
|
||||
if (e.semNum == sem->semNum && e.semId == id)
|
||||
{
|
||||
timerQueue->remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stopTimers(void*)
|
||||
{
|
||||
timerHolder.cleanup();
|
||||
}
|
||||
|
||||
THREAD_ENTRY_DECLARE TimerEntry::timeThread(THREAD_ENTRY_PARAM)
|
||||
{
|
||||
while (!stopThread)
|
||||
{
|
||||
int microSeconds = 0;
|
||||
{
|
||||
MutexLockGuard guard(timerAccess);
|
||||
|
||||
const SINT64 cur = curTime();
|
||||
while (timerQueue->getCount() > 0)
|
||||
{
|
||||
const TimerEntry& e(timerQueue->operator[](0));
|
||||
if (e.fireTime <= cur)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
union semun arg;
|
||||
arg.val = 0;
|
||||
int ret = semctl(e.semId, e.semNum, SETVAL, arg);
|
||||
if (ret != -1)
|
||||
break;
|
||||
if (!SYSCALL_INTERRUPTED(errno))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
timerQueue->remove((size_t) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
microSeconds = e.fireTime - cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (microSeconds)
|
||||
{
|
||||
timerWakeup->tryEnter(0, microSeconds / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
timerWakeup->enter();
|
||||
}
|
||||
}
|
||||
|
||||
timerFini->release();
|
||||
return 0;
|
||||
SINT64 rc = ((SINT64) cur_time.tv_sec) * 1000000 + cur_time.tv_usec;
|
||||
return rc;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -928,7 +1018,9 @@ void ISC_event_fini(event_t* event)
|
||||
*
|
||||
**************************************/
|
||||
IPC_TRACE(("ISC_event_fini set=%d num=%d\n", event->semSet, event->semNum));
|
||||
finiStart(event);
|
||||
freeSem5(event);
|
||||
finiStop(event);
|
||||
}
|
||||
|
||||
|
||||
@ -944,12 +1036,14 @@ int ISC_event_init(event_t* event)
|
||||
* Prepare an event object for use.
|
||||
*
|
||||
**************************************/
|
||||
initStart(event);
|
||||
|
||||
event->event_count = 0;
|
||||
|
||||
if (!getSem5(event))
|
||||
{
|
||||
IPC_TRACE(("ISC_event_init failed get sem %p\n", event));
|
||||
initStop(event, 1);
|
||||
return FB_FAILURE;
|
||||
}
|
||||
|
||||
@ -959,11 +1053,13 @@ int ISC_event_init(event_t* event)
|
||||
arg.val = 0;
|
||||
if (semctl(event->getId(), event->semNum, SETVAL, arg) < 0)
|
||||
{
|
||||
initStop(event, 2);
|
||||
iscLogStatus("event_init()",
|
||||
(Arg::Gds(isc_sys_request) << Arg::Str("semctl") << SYS_ERR(errno)).value());
|
||||
return FB_FAILURE;
|
||||
}
|
||||
|
||||
initStop(event, 0);
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1031,7 +1127,8 @@ int ISC_event_wait(event_t* event, SLONG value, const SLONG micro_seconds)
|
||||
SINT64 timeout = 0;
|
||||
if (micro_seconds > 0)
|
||||
{
|
||||
timeout = addTimer(event, micro_seconds);
|
||||
timeout = curTime() + micro_seconds;
|
||||
addTimer(event, micro_seconds);
|
||||
}
|
||||
|
||||
// Go into wait loop
|
||||
@ -3543,8 +3640,7 @@ static SLONG create_semaphores(Arg::StatusVector& statusVector, SLONG key, int s
|
||||
{
|
||||
// We want to limit access to semaphores, created here
|
||||
// Reasonable access rights to them - exactly like security database has
|
||||
char secDb[MAXPATHLEN];
|
||||
Auth::SecurityDatabase::getPath(secDb);
|
||||
const char* secDb = Config::getDefaultConfig()->getSecurityDatabase();
|
||||
struct stat st;
|
||||
if (stat(secDb, &st) == 0)
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ EventManager::~EventManager()
|
||||
{
|
||||
// Terminate the event watcher thread
|
||||
m_startupSemaphore.tryEnter(5);
|
||||
ISC_event_post(&m_process->prb_event);
|
||||
(void) ISC_event_post(&m_process->prb_event);
|
||||
m_cleanupSemaphore.tryEnter(5);
|
||||
|
||||
#ifdef HAVE_OBJECT_MAP
|
||||
@ -393,7 +393,11 @@ SLONG EventManager::queEvents(SLONG session_id,
|
||||
|
||||
if (flag)
|
||||
{
|
||||
post_process((prb*) SRQ_ABS_PTR(m_processOffset));
|
||||
if (!post_process((prb*) SRQ_ABS_PTR(m_processOffset)))
|
||||
{
|
||||
release_shmem();
|
||||
(Firebird::Arg::Gds(isc_random) << "post_process() failed").raise();
|
||||
}
|
||||
}
|
||||
|
||||
release_shmem();
|
||||
@ -513,7 +517,11 @@ void EventManager::deliverEvents()
|
||||
prb* const process = (prb*) ((UCHAR*) event_srq - OFFSET (prb*, prb_processes));
|
||||
if (process->prb_flags & PRB_wakeup)
|
||||
{
|
||||
post_process(process);
|
||||
if (!post_process(process))
|
||||
{
|
||||
release_shmem();
|
||||
(Firebird::Arg::Gds(isc_random) << "post_process() failed").raise();
|
||||
}
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
@ -682,7 +690,11 @@ void EventManager::create_process()
|
||||
insert_tail(&sh_mem_header->evh_processes, &process->prb_processes);
|
||||
SRQ_INIT(process->prb_sessions);
|
||||
|
||||
ISC_event_init(&process->prb_event);
|
||||
if (ISC_event_init(&process->prb_event) != FB_SUCCESS)
|
||||
{
|
||||
release_shmem();
|
||||
(Firebird::Arg::Gds(isc_random) << "ISC_event_init() failed").raise();
|
||||
}
|
||||
|
||||
m_processOffset = SRQ_REL_PTR(process);
|
||||
|
||||
@ -1205,7 +1217,7 @@ void EventManager::mutex_bugcheck(const TEXT* string, int mutex_state)
|
||||
}
|
||||
|
||||
|
||||
void EventManager::post_process(prb* process)
|
||||
bool EventManager::post_process(prb* process)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1219,7 +1231,7 @@ void EventManager::post_process(prb* process)
|
||||
**************************************/
|
||||
process->prb_flags &= ~PRB_wakeup;
|
||||
process->prb_flags |= PRB_pending;
|
||||
ISC_event_post(&process->prb_event);
|
||||
return ISC_event_post(&process->prb_event) == FB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -1424,7 +1436,7 @@ void EventManager::watcher_thread()
|
||||
if (m_exiting)
|
||||
break;
|
||||
|
||||
ISC_event_wait(&m_process->prb_event, value, 0);
|
||||
(void) ISC_event_wait(&m_process->prb_event, value, 0);
|
||||
}
|
||||
|
||||
m_cleanupSemaphore.release();
|
||||
|
@ -81,7 +81,7 @@ private:
|
||||
req_int* historical_interest(ses*, SLONG);
|
||||
void insert_tail(srq*, srq*);
|
||||
evnt* make_event(USHORT, const TEXT*, SLONG);
|
||||
void post_process(prb*);
|
||||
bool post_process(prb*);
|
||||
void probe_processes();
|
||||
void release_shmem();
|
||||
void remove_que(srq*);
|
||||
|
@ -250,6 +250,7 @@ LockManager::~LockManager()
|
||||
m_startupSemaphore.tryEnter(5);
|
||||
|
||||
// Wakeup the AST thread - it might be blocking
|
||||
(void) // Ignore errors in dtor()
|
||||
ISC_event_post(&m_process->prc_blocking);
|
||||
|
||||
// Wait for the AST thread to finish cleanup or for 5 seconds
|
||||
@ -1549,7 +1550,7 @@ void LockManager::blocking_action_thread()
|
||||
}
|
||||
}
|
||||
|
||||
ISC_event_wait(&m_process->prc_blocking, value, 0);
|
||||
(void) ISC_event_wait(&m_process->prc_blocking, value, 0);
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception& x)
|
||||
@ -1736,7 +1737,11 @@ bool LockManager::create_owner(Arg::StatusVector& statusVector,
|
||||
remove_que(&owner->own_lhb_owners);
|
||||
}
|
||||
|
||||
init_owner_block(owner, owner_type, owner_id);
|
||||
if (!init_owner_block(statusVector, owner, owner_type, owner_id))
|
||||
{
|
||||
release_mutex();
|
||||
return false;
|
||||
}
|
||||
|
||||
insert_tail(&sh_mem_header->lhb_owners, &owner->own_lhb_owners);
|
||||
|
||||
@ -1802,7 +1807,11 @@ bool LockManager::create_process(Arg::StatusVector& statusVector)
|
||||
|
||||
insert_tail(&sh_mem_header->lhb_processes, &process->prc_lhb_processes);
|
||||
|
||||
ISC_event_init(&process->prc_blocking);
|
||||
if (ISC_event_init(&process->prc_blocking) != FB_SUCCESS)
|
||||
{
|
||||
statusVector << Arg::Gds(isc_lockmanerr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_processOffset = SRQ_REL_PTR(process);
|
||||
|
||||
@ -2298,7 +2307,7 @@ SRQ_PTR LockManager::grant_or_que(Attachment* attachment, lrq* request, lbl* loc
|
||||
}
|
||||
|
||||
|
||||
void LockManager::init_owner_block(own* owner, UCHAR owner_type, LOCK_OWNER_T owner_id)
|
||||
bool LockManager::init_owner_block(Arg::StatusVector& statusVector, own* owner, UCHAR owner_type, LOCK_OWNER_T owner_id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2326,7 +2335,13 @@ void LockManager::init_owner_block(own* owner, UCHAR owner_type, LOCK_OWNER_T ow
|
||||
owner->own_acquire_time = 0;
|
||||
owner->own_ast_count = 0;
|
||||
|
||||
ISC_event_init(&owner->own_wakeup);
|
||||
if (ISC_event_init(&owner->own_wakeup) != FB_SUCCESS)
|
||||
{
|
||||
statusVector << Arg::Gds(isc_lockmanerr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -2916,7 +2931,7 @@ void LockManager::post_wakeup(own* owner)
|
||||
{
|
||||
++sh_mem_header->lhb_wakeups;
|
||||
owner->own_flags |= OWN_wakeup;
|
||||
ISC_event_post(&owner->own_wakeup);
|
||||
(void) ISC_event_post(&owner->own_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3067,7 +3082,10 @@ void LockManager::remap_local_owners()
|
||||
own* owner = (own*) ((UCHAR*) lock_srq - OFFSET(own*, own_prc_owners));
|
||||
if (owner->own_flags & OWN_waiting)
|
||||
{
|
||||
ISC_event_post(&owner->own_wakeup);
|
||||
if (ISC_event_post(&owner->own_wakeup) != FB_SUCCESS)
|
||||
{
|
||||
bug(NULL, "remap failed: ISC_event_post() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ private:
|
||||
lrq* get_request(SRQ_PTR);
|
||||
void grant(lrq*, lbl*);
|
||||
SRQ_PTR grant_or_que(Attachment*, lrq*, lbl*, SSHORT);
|
||||
void init_owner_block(own*, UCHAR, LOCK_OWNER_T);
|
||||
bool init_owner_block(Firebird::Arg::StatusVector&, own*, UCHAR, LOCK_OWNER_T);
|
||||
void insert_data_que(lbl*);
|
||||
void insert_tail(SRQ, SRQ);
|
||||
bool internal_convert(Attachment* database, Firebird::Arg::StatusVector&, SRQ_PTR, UCHAR, SSHORT,
|
||||
|
Loading…
Reference in New Issue
Block a user