mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 12:03:02 +01:00
Better fix for CORE-3786: Firebird 2.5.1 Classic (32-bit) Hangs on MacOSX 10.7 (Lion) on DB create after reboot
This commit is contained in:
parent
5374b683ce
commit
04c02049dd
@ -159,10 +159,29 @@ static bool event_blocked(const event_t* event, const SLONG value);
|
|||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
|
|
||||||
|
#if defined(USE_FILELOCKS) || (!defined(HAVE_FLOCK))
|
||||||
|
#define USE_FCNTL
|
||||||
|
#endif
|
||||||
|
|
||||||
static GlobalPtr<Mutex> openFdInit;
|
static GlobalPtr<Mutex> openFdInit;
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
#ifdef USE_FCNTL
|
||||||
|
|
||||||
|
struct CountedRWLock
|
||||||
|
{
|
||||||
|
RWLock rwlock;
|
||||||
|
AtomicCounter cnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef GenericMap<Pair<Left<string, CountedRWLock> > > RWLocks;
|
||||||
|
GlobalPtr<RWLocks> rwlocks;
|
||||||
|
GlobalPtr<Mutex> rwlocksMutex;
|
||||||
|
|
||||||
|
#endif // USE_FCNTL
|
||||||
|
|
||||||
// File lock holder
|
// File lock holder
|
||||||
class FileLock
|
class FileLock
|
||||||
{
|
{
|
||||||
@ -172,22 +191,43 @@ namespace {
|
|||||||
enum LockMode {FLM_EXCLUSIVE, FLM_TRY_EXCLUSIVE, FLM_SHARED, FLM_TRY_SHARED};
|
enum LockMode {FLM_EXCLUSIVE, FLM_TRY_EXCLUSIVE, FLM_SHARED, FLM_TRY_SHARED};
|
||||||
|
|
||||||
FileLock(int pFd, DtorMode pMode = CLOSED, int s = 0)
|
FileLock(int pFd, DtorMode pMode = CLOSED, int s = 0)
|
||||||
: level(LCK_NONE), fd(pFd), dtorMode(pMode), start(s)
|
: level(LCK_NONE), fd(pFd), dtorMode(pMode)
|
||||||
|
#ifdef USE_FCNTL
|
||||||
|
, start(s), rwlock(getRw())
|
||||||
|
#endif
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~FileLock()
|
~FileLock()
|
||||||
{
|
{
|
||||||
switch (dtorMode)
|
if (dtorMode != LOCKED)
|
||||||
{
|
{
|
||||||
case LOCKED:
|
#ifdef USE_FCNTL
|
||||||
break;
|
MutexLockGuard g(rwlocksMutex);
|
||||||
case OPENED:
|
#ifdef DEBUG_RWLOCKS
|
||||||
unlock();
|
fprintf(stderr, "\n-- %p\n", rwlock);
|
||||||
break;
|
#endif
|
||||||
case CLOSED:
|
if (--(rwlock->cnt) == 0)
|
||||||
|
{
|
||||||
|
unlock();
|
||||||
|
#ifdef DEBUG_RWLOCKS
|
||||||
|
fprintf(stderr, "\nremove %p\n", rwlock);
|
||||||
|
#endif
|
||||||
|
rwlocks->remove(getLockId());
|
||||||
|
}
|
||||||
|
#else
|
||||||
unlock();
|
unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_RWLOCKS
|
||||||
|
fprintf(stderr, "\nlocked %p\n", rwlock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtorMode == CLOSED)
|
||||||
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,18 +239,38 @@ namespace {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_FCNTL
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
lock.l_type = F_UNLCK;
|
lock.l_type = F_UNLCK;
|
||||||
lock.l_whence = SEEK_SET;
|
lock.l_whence = SEEK_SET;
|
||||||
lock.l_start = start;
|
lock.l_start = start;
|
||||||
lock.l_len = 1;
|
lock.l_len = 1;
|
||||||
if (fcntl(fd, F_SETLK, &lock) == -1)
|
if (fcntl(fd, F_SETLK, &lock) == 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (level == LCK_SHARED)
|
||||||
|
rwlock->rwlock.endRead();
|
||||||
|
else
|
||||||
|
rwlock->rwlock.endWrite();
|
||||||
|
}
|
||||||
|
catch(const Exception& ex)
|
||||||
|
{
|
||||||
|
iscLogException("Unlock error", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (flock(fd, LOCK_UN) == 0)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
level = LCK_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ISC_STATUS_ARRAY local;
|
ISC_STATUS_ARRAY local;
|
||||||
error(local, "fcntl", errno);
|
error(local, "fcntl", errno);
|
||||||
iscLogStatus("Unlock error", local);
|
iscLogStatus("Unlock error", local);
|
||||||
}
|
}
|
||||||
level = LCK_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main method to lock file
|
// Main method to lock file
|
||||||
@ -242,14 +302,59 @@ namespace {
|
|||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_FCNTL
|
||||||
|
bool rc = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case FLM_TRY_EXCLUSIVE:
|
||||||
|
rc = rwlock->rwlock.tryBeginWrite();
|
||||||
|
break;
|
||||||
|
case FLM_EXCLUSIVE:
|
||||||
|
rwlock->rwlock.beginWrite();
|
||||||
|
break;
|
||||||
|
case FLM_TRY_SHARED:
|
||||||
|
rc = rwlock->rwlock.tryBeginRead();
|
||||||
|
break;
|
||||||
|
case FLM_SHARED:
|
||||||
|
rwlock->rwlock.beginRead();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const system_call_failed& fail)
|
||||||
|
{
|
||||||
|
return fail.getErrorCode();
|
||||||
|
}
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
lock.l_type = shared ? F_RDLCK : F_WRLCK;
|
lock.l_type = shared ? F_RDLCK : F_WRLCK;
|
||||||
lock.l_whence = SEEK_SET;
|
lock.l_whence = SEEK_SET;
|
||||||
lock.l_start = start;
|
lock.l_start = start;
|
||||||
lock.l_len = 1;
|
lock.l_len = 1;
|
||||||
if (fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock) == -1)
|
if (fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock) == -1)
|
||||||
|
{
|
||||||
|
int rc = errno;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (newLevel == LCK_SHARED)
|
||||||
|
rwlock->rwlock.endRead();
|
||||||
|
else
|
||||||
|
rwlock->rwlock.endWrite();
|
||||||
|
}
|
||||||
|
catch(const Exception&)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
#else
|
||||||
|
if (flock(fd, (shared ? LOCK_SH : LOCK_EX) | (wait ? 0 : LOCK_NB)))
|
||||||
{
|
{
|
||||||
return errno;
|
return errno;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
level = newLevel;
|
level = newLevel;
|
||||||
|
|
||||||
@ -279,13 +384,68 @@ namespace {
|
|||||||
void setLevel(LockLevel l)
|
void setLevel(LockLevel l)
|
||||||
{
|
{
|
||||||
level = l;
|
level = l;
|
||||||
|
#ifdef USE_FCNTL
|
||||||
|
if (level != LCK_NONE)
|
||||||
|
{
|
||||||
|
// was not done in dtor
|
||||||
|
--(rwlock->cnt);
|
||||||
|
#ifdef DEBUG_RWLOCKS
|
||||||
|
fprintf(stderr, "\n-- %p\n", rwlock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LockLevel level;
|
LockLevel level;
|
||||||
int fd;
|
int fd;
|
||||||
DtorMode dtorMode;
|
DtorMode dtorMode;
|
||||||
|
#ifdef USE_FCNTL
|
||||||
int start;
|
int start;
|
||||||
|
CountedRWLock* rwlock; // Due to order of init in ctor rwlock must go after fd & start
|
||||||
|
|
||||||
|
string getLockId()
|
||||||
|
{
|
||||||
|
struct stat statistics;
|
||||||
|
fstat(fd, &statistics);
|
||||||
|
|
||||||
|
const size_t len1 = sizeof(statistics.st_dev);
|
||||||
|
const size_t len2 = sizeof(statistics.st_ino);
|
||||||
|
const size_t len3 = sizeof(int);
|
||||||
|
|
||||||
|
string rc(len1 + len2 + len3, ' ');
|
||||||
|
char* p = rc.begin();
|
||||||
|
|
||||||
|
memcpy(p, &statistics.st_dev, len1);
|
||||||
|
p += len1;
|
||||||
|
memcpy(p, &statistics.st_ino, len2);
|
||||||
|
p += len2;
|
||||||
|
memcpy(p, &start, len3);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CountedRWLock* getRw()
|
||||||
|
{
|
||||||
|
string id = getLockId();
|
||||||
|
|
||||||
|
MutexLockGuard g(rwlocksMutex);
|
||||||
|
CountedRWLock* rc = rwlocks->get(id);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
rc = rwlocks->put(id);
|
||||||
|
#ifdef DEBUG_RWLOCKS
|
||||||
|
fprintf(stderr, "\ncreated %p\n", rc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
++(rc->cnt);
|
||||||
|
#ifdef DEBUG_RWLOCKS
|
||||||
|
fprintf(stderr, "\n++ %p\n", rc);
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2084,6 +2244,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
|||||||
|
|
||||||
/* keep opened the shared file_decriptor */
|
/* keep opened the shared file_decriptor */
|
||||||
mainLock.setDtorMode(FileLock::LOCKED);
|
mainLock.setDtorMode(FileLock::LOCKED);
|
||||||
|
|
||||||
#ifdef USE_SYS5SEMAPHORE
|
#ifdef USE_SYS5SEMAPHORE
|
||||||
// keep shared lock before last shared memory region unmapped
|
// keep shared lock before last shared memory region unmapped
|
||||||
semLock.setDtorMode(FileLock::LOCKED);
|
semLock.setDtorMode(FileLock::LOCKED);
|
||||||
@ -2778,6 +2939,7 @@ int ISC_mutex_lock(struct mtx* mutex)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#endif // USE_FILELOCKS
|
#endif // USE_FILELOCKS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2825,6 +2987,7 @@ int ISC_mutex_lock_cond(struct mtx* mutex)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#endif // USE_FILELOCKS
|
#endif // USE_FILELOCKS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3765,7 +3928,7 @@ void ISC_unmap_file(ISC_STATUS* status_vector, sh_mem* shmem_data)
|
|||||||
|
|
||||||
TEXT expanded_filename[MAXPATHLEN];
|
TEXT expanded_filename[MAXPATHLEN];
|
||||||
gds__prefix_lock(expanded_filename, shmem_data->sh_mem_name);
|
gds__prefix_lock(expanded_filename, shmem_data->sh_mem_name);
|
||||||
|
|
||||||
// Delete file only if it is not used by anyone else
|
// Delete file only if it is not used by anyone else
|
||||||
HANDLE hFile = CreateFile(expanded_filename,
|
HANDLE hFile = CreateFile(expanded_filename,
|
||||||
DELETE,
|
DELETE,
|
||||||
|
Loading…
Reference in New Issue
Block a user