Opened 6 years ago

Last modified 5 years ago

#12947 new Bugs

Failed to use memory-mapped file to interprocess communications

Reported by: Valeriy N. Sifurov <vsifurov@…> Owned by: Jonathan Turkanis
Milestone: To Be Determined Component: iostreams
Version: Boost 1.63.0 Severity: Problem
Keywords: Cc:

Description

In first process we create and write the memory-mapped file through boost::iostreams::mapped_file_sink with boost::iostreams::mapped_file::readwrite flag. In seconde process we attempt to open the same memory-mapped file for read through boost::iostreams::mapped_file_source with boost::iostreams::mapped_file::readonly flag. The aptempt has failed for second process. Windows error code 32 (The process cannot access the file because it is being used by another process). In source code of iostream library we discover the next code that attempt to open file (mapped_file.cpp, void mapped_file_impl::open_file(param_type p)):

DWORD dwDesiredAccess =

readonly ?

GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);

DWORD dwCreationDisposition = (p.new_file_size != 0 && !readonly) ?

CREATE_ALWAYS : OPEN_EXISTING;

DWORD dwFlagsandAttributes =

readonly ?

FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_TEMPORARY;

handle_ = p.path.is_wide() ?

::CreateFileW(

p.path.c_wstr(), dwDesiredAccess, FILE_SHARE_READ, NULL, dwCreationDisposition, dwFlagsandAttributes, NULL ) :

::CreateFileA(

p.path.c_str(), dwDesiredAccess, FILE_SHARE_READ, NULL, dwCreationDisposition, dwFlagsandAttributes, NULL );

if (handle_ == INVALID_HANDLE_VALUE)

cleanup_and_throw("failed opening file");

In both cases (opening the file for write of for read) the dwShareMode flag has FILE_SHARE_READ value. This is wrong! Using the rules that dуscraybed on page https://msdn.microsoft.com/en-us/library/windows/desktop/aa363874(v=vs.85).aspx we corrected the code of function:

DWORD dwDesiredAccess =

readonly ?

GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);

DWORD dwCreationDisposition = (p.new_file_size != 0 && !readonly) ?

CREATE_ALWAYS : OPEN_EXISTING;

DWORD dwFlagsandAttributes =

readonly ?

FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_TEMPORARY;

handle_ = p.path.is_wide() ?

::CreateFileW(

p.path.c_wstr(), dwDesiredAccess, !readonly ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, dwCreationDisposition, dwFlagsandAttributes, NULL ) :

::CreateFileA(

p.path.c_str(), dwDesiredAccess, !readonly ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, dwCreationDisposition, dwFlagsandAttributes, NULL );

if (handle_ == INVALID_HANDLE_VALUE)

cleanup_and_throw("failed opening file");

Attachments (1)

mapped_file.hpp (19.1 KB ) - added by Valeriy N. Sifurov <vsifurov@…> 6 years ago.
Corrected code

Download all attachments as: .zip

Change History (3)

by Valeriy N. Sifurov <vsifurov@…>, 6 years ago

Attachment: mapped_file.hpp added

Corrected code

comment:1 by Mateusz Loskot, 5 years ago

Is there any chance this fix could be accepted?

comment:2 by anonymous, 5 years ago

Yeah, unless there is some other way to open the same memory mapped file from two processes, this seems to prevent that use case :-(. Not everyone may want to use boost::interprocess!

Note: See TracTickets for help on using tickets.