mirror of
https://github.com/znc/znc.git
synced 2026-03-28 17:42:41 +01:00
Use fcntl() instead of flock() for locking the config file
fcntl() is more portable than flock() so this makes znc run on more systems (everyone smile and say hi to solaris). The downside is that fcntl() locks are lost if *any* fd referring to that file is closed (luckily we don't do that). The big downside is that the child process after fork() does not inherit the lock. To work around this, when znc forks into the background, the child process immediately blocks and tries to get the lock on the config file. Once the parent releases the lock by exiting, the child will get it. This shouldn't cause races with other ZNCs, because in every other place we don't block waiting for a lock but instead abort immediately if the file is already locked. Thanks to LeftWing aka Joshua M. Clulow for making znc work on solaris (and automatically fixing some issues with NFS in the process). git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2065 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef HAVE_LSTAT
|
||||
# define lstat(a, b) stat(a, b)
|
||||
@@ -388,23 +389,33 @@ bool CFile::TryExLock(const CString& sLockFile, int iFlags) {
|
||||
}
|
||||
|
||||
bool CFile::TryExLock() {
|
||||
return Lock(LOCK_EX|LOCK_NB);
|
||||
return Lock(F_WRLCK, false);
|
||||
}
|
||||
|
||||
bool CFile::ExLock() {
|
||||
return Lock(F_WRLCK, true);
|
||||
}
|
||||
|
||||
bool CFile::UnLock() {
|
||||
return Lock(LOCK_UN);
|
||||
return Lock(F_UNLCK, true);
|
||||
}
|
||||
|
||||
bool CFile::Lock(int iOperation) {
|
||||
bool CFile::Lock(int iType, bool bBlocking) {
|
||||
struct flock fl;
|
||||
|
||||
if (m_iFD == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flock(m_iFD, iOperation) != 0) {
|
||||
fl.l_type = iType;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
if (fcntl(m_iFD, (bBlocking ? F_SETLKW : F_SETLK), &fl) == -1) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFile::IsOpen() const { return (m_iFD != -1); }
|
||||
|
||||
Reference in New Issue
Block a user