Ticket #2796 (closed Bugs: fixed)
interprocess::file_lock has incorrect behavior when win32 api is enabled
|Reported by:||Kelly K. Heller <kkheller@…>||Owned by:||igaztanaga|
|Keywords:||file descriptor fd getfd file handle handle file pointer win32 winapi fstream ifstream ofstream std createfile lock locking||Cc:|
(Above all else, I must say.... boost is awesome. I am raving fan of boost. Many, many thanks to all the talented boost developers.)
Either the IPC file_lock documentation needs fixing, or else there is a bug in the way file_lock uses win32 file handles and LockFileEx?.
This part of the boost documentation is incorrect when the win32 api is enabled:
The problem with the sample code at the above URL is that on windows, "fstream file" and "file_lock f_lock" both will hold TWO DIFFERENT file handles. Of course both of those objects wrap the same exact file on disk, but it is _crucial_ (and in this case deadly) to realize that they wrap different HANDLES.
So... when using the win32 api in boost file_lock, the last line of code in the sample from the URL will always fail.
This will always fail:
Windows will produce an ERROR_LOCK_VIOLATION. As I explain below, the reason why this happens is that locking in the windows api actually locks write-access to the file based on the HANDLE, not based on the process (pid) that obtained the locking rights.
This basically makes boost file_lock incompatible, or not successfully ported, to windows. I essentially "lock myself out of the file" when I use the file_lock. Obviously that is _not_ what one wants. We want to lock other processes out of the file, but not lock ourselves out.
Please note the following win32 documentation:
The interesting part about LockFileEx? is the following:
If the locking process opens the file a second time, it cannot access the specified region through this second handle until it unlocks the region..... "
The important thing about that is that LockFileEx? is doing MORE than making sure foreign processes are locked out of my file. LockFileEx? will also keep my process (the process obtaining the lock) from writing to the file, unless I am careful to use an IDENTICAL file handle.
As far as I can see, this makes LockFileEx? very different from flock().
So, if I am to follow the windows advice for using LockFileEx?, then I believe what I need to do is make sure that the same file handle I use to write to my file is IDENTICAL to the file handle used by my boost file_lock object.
Unfortunately, I cannot see any way to do this. And unless I can find a way, then it seems like boost::interprocess:file_lock is not useful at all when the win32 api is enabled.
in the ctor of the file_lock, "open_existing_file" is called, which calls the winapi function CreateFileA.
CreateFileA gives you a new file handle. This file handle is stored (privately) in:
When you then proceed to _lock_ the file_lock, the winapi function LockFileEx?.
LockFileEx? takes a handle as an argument. As we would expect, the handle that gets passed in is the same handle as file_lock::m_file_hnd.
The problem is that the win32 api will now lock out (prevent) all writes to the file that are not writing via that same file handle.
That means that even the process that obtained and now holds the locked file_lock is prevented from writing to the file.
This is the windows error that happens:
33 The process cannot access the file because another process has locked a portion of the file. ERROR_LOCK_VIOLATION
Because "file_lock::m_file_hnd" is a private member, I cannot see any way for me to use any object (and file object, whether it be a win32 object that I construct, or a std::fstream, or some other file object)... I cannot see a way for myself to get a file object with the SAME handle as file_lock::m_file_hnd, which is what I must do if I even am going to actually write to the file that i have locked with file_lock.
- Version changed from Boost 1.37.0 to Boost 1.38.0
- Status changed from new to closed
- Resolution set to fixed
- Status changed from closed to reopened
- Resolution fixed deleted
- Milestone Boost 1.39.0 deleted
- Status changed from reopened to closed
- Resolution set to fixed