[Boost-bugs] [Boost C++ Libraries] #2796: interprocess::file_lock has incorrect behavior when win32 api is enabled

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