Subject: [Boost-bugs] [Boost C++ Libraries] #2796: interprocess::file_lock has incorrect behavior when win32 api is enabled
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-02-24 01:11:06
#2796: interprocess::file_lock has incorrect behavior when win32 api is enabled
-----------------------------------------------------------------------------------------------------------------------------------------+
Reporter: Kelly K. Heller <kkheller_at_[hidden]> | Owner: igaztanaga
Type: Bugs | Status: new
Milestone: Boost 1.39.0 | Component: interprocess
Version: Boost 1.37.0 | Severity: Problem
Keywords: file descriptor fd getfd file handle handle file pointer win32 winapi fstream ifstream ofstream std createfile lock locking |
-----------------------------------------------------------------------------------------------------------------------------------------+
(Above all else, I must say.... boost is awesome. I am raving fan of
boost. Many, many thanks to all the talented boost developers.)
BUG DESCRIPTION:
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:
http://www.boost.org/doc/libs/1_36_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_careful_iostream
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:
file.flush();
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:
http://msdn.microsoft.com/en-us/library/aa365203(VS.85).aspx
The interesting part about LockFileEx is the following:
"Remarks .....
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:
file_lock::m_file_hnd
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.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/2796> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:59 UTC