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:
psychon
2010-07-05 16:13:23 +00:00
parent 84ae0f2edd
commit 33ce80f476
5 changed files with 38 additions and 9 deletions
+10
View File
@@ -254,6 +254,16 @@ int main(int argc, char** argv) {
return 0;
}
/* fcntl() locks don't necessarily propagate to forked()
* children. Reacquire the lock here. Use the blocking
* call to avoid race condition with parent exiting.
*/
if (!pZNC->WaitForChildLock()) {
CUtils::PrintError("Child was unable to obtain lock on config file.");
delete pZNC;
return 1;
}
// Redirect std in/out/err to /dev/null
close(0); open("/dev/null", O_RDONLY);
close(1); open("/dev/null", O_WRONLY);