The proper way to use lock files as locks between multiple processes

I have a situation where two different processes (my C ++, the other made by other people in JAVA) are a writer and a reader from some common data file. So I tried to avoid the race state by writing a class like this (EDIT: this code is broken, it was just an example)

class ReadStatus { bool canRead; public: ReadStatus() { if (filesystem::exists(noReadFileName)) { canRead = false; return; } ofstream noWriteFile; noWriteFile.open (noWriteFileName.c_str()); if ( ! noWriteFile.is_open()) { canRead = false; return; } boost::this_thread::sleep(boost::posix_time::seconds(1)); if (filesystem::exists(noReadFileName)) { filesystem::remove(noWriteFileName); canRead= false; return; } canRead= true; } ~ReadStatus() { if (filesystem::exists(noWriteFileName)) filesystem::remove(noWriteFileName); } inline bool OKToRead() { return canRead; } }; 

using:

 ReadStatus readStatus; //RAII FTW if ( ! readStatus.OKToRead()) return; 

This is for one ofc program, the other will have a similar class. Idea: 1. check if another program created its file "I am the owner" if it has a breakthrough 2. 2. create a file "I am the owner", check again if another program created it if it deletes my file and breaks another 3. 3. do my reading, then delete my "I am the owner file."

Please note that the rare cases when they both do not read and do not write are okay, but the problem is that I still see a small chance of race conditions, because theoretically another program can check for the presence of my lock file, see that no one, then I create my own, another program creates my own, but before FS creates my file, I will check again, and this is not so, then a catastrophe occurs. That's why I added a 1 second delay, but as a CS nerd, I find that he is nervous so that the code works like this. Ofc. I do not expect anyone here to write me a solution, but I would be glad if someone knows a link to reliable code that I can use. PS It should be files, because I am not writing the whole project, and so it should be done.

PPS: access to the data file is not a reader, writer, reader, writer .... it can be a reader, reader, writer, writer, writer, reader, writer ....

PPS: another process is not written in C ++ :(, so boost is out of the question.

+4
source share
3 answers

In Unices, the traditional way to lock based on a clean file system is to use dedicated lockfiles with mkdir() and rmdir() , which can be created and deleted atomically using single system calls. You avoid racing by never checking for the explicit existence of a lock - instead, you always try to take a lock. So:

 lock: while mkdir(lockfile) fails sleep unlock: rmdir(lockfile) 

I find this even works on NFS (which usually sucks for this kind of thing).

However, you probably also want to learn the correct file locking, which loads better; I use F_SETLK / F_UNLCK fcntl locks for this on Linux (note that they are different from locks, despite the name of the structure). This allows the lock until the lock is released. These locks are also automatically released if the application dies, which is usually good. In addition, they will allow you to lock your shared file directly without having a separate lock file. This also works on NFS.

Windows has very similar file locking features, and also has easy-to-use global semaphores that are very convenient for synchronizing between processes.

+5
source

As far as I saw, you cannot reliably use files as locks for several processes. The problem is that when you create a file in one thread, you can get an interrupt, and the OS switches to another process, because I / O takes a lot of time. The same is true for deleting a lock file.

If you can, see Boost.Interprocess in the synchronization mechanisms section.

+3
source

While I am generally opposed to API calls that can be selected from the constructor / destructor (see documents on boost::filesystem::remove ) or making call calls without blocking in general, this is actually not what you are talking about requested.

You can check the Overlapped IO library if it is for Windows. Otherwise, you considered instead of shared memory between processes ?

Edit: just saw that the other process was Java. You can still create a named mutex that can be shared between processes and use it to create locks around the file I / O bits so that they can write in turn. Sorry, I do not know Java, so there is no idea if this is more possible than shared memory.

+1
source

All Articles