diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 4fd79c6..7b0fe68 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -6780,6 +6780,7 @@ thank them: * Minor documentation fixes * Fixed bugs: * [@https://github.com/boostorg/interprocess/pull/245 GitHub #245 (['"Fix UBSan runtime error (load of 'boost::interprocess::mode_t')"])]. + * [@https://github.com/boostorg/interprocess/issues/261 GitHub #261 (['"Memory Mapping Empty Files Fails"])]. * [@https://github.com/boostorg/interprocess/pull/269 GitHub #269 (['"Minor documentation fixes and template parameter renames"])]. * [@https://github.com/boostorg/interprocess/issues/272 GitHub #272 (['"Regression boost 1.87: offset_ptr conversion from void no longer works"])]. * [@https://github.com/boostorg/interprocess/pull/275 GitHub #275 (['"Allow injection of custom atexit procedure"])]. diff --git a/include/boost/interprocess/file_mapping.hpp b/include/boost/interprocess/file_mapping.hpp index 88268fa..423c3f3 100644 --- a/include/boost/interprocess/file_mapping.hpp +++ b/include/boost/interprocess/file_mapping.hpp @@ -109,6 +109,10 @@ class file_mapping //!used in the constructor. const char *get_name() const BOOST_NOEXCEPT; + //!Returns true if the size of the file memory object + //!can be obtained and writes the size in the passed reference. + bool get_size(offset_t &size) const BOOST_NOEXCEPT; + //!Removes the file named "filename" even if it's been memory mapped. //!Returns true on success. //!The function might fail in some operating systems if the file is @@ -147,6 +151,9 @@ inline file_mapping::~file_mapping() inline const char *file_mapping::get_name() const BOOST_NOEXCEPT { return m_filename.getn(); } +inline bool file_mapping::get_size(offset_t &size) const BOOST_NOEXCEPT +{ return ipcdetail::get_file_size((file_handle_t)m_handle, size); } + inline void file_mapping::swap(file_mapping &other) BOOST_NOEXCEPT { (simple_swap)(m_handle, other.m_handle); diff --git a/include/boost/interprocess/mapped_region.hpp b/include/boost/interprocess/mapped_region.hpp index a76e0c4..b410de4 100644 --- a/include/boost/interprocess/mapped_region.hpp +++ b/include/boost/interprocess/mapped_region.hpp @@ -102,6 +102,13 @@ class mapped_region //!offset "offset", and the mapping's size will be "size". The mapping //!can be opened for read only, read-write or copy-on-write. //! + //!The "mapping" object must be an non-empty mappable type (file, shared memory...) + //!or the function might fail. Check `shared_memory_object/file_mapping::get_size() != 0` + //!before trying to map the empty object and obtain an error. + //! + //!The "size" parameter must be bigger than zero or the function will fail + //! + //! //!If an address is specified, both the offset and the address must be //!multiples of the page size. //! diff --git a/test/file_mapping_test.cpp b/test/file_mapping_test.cpp index f52a3bc..3a8e688 100644 --- a/test/file_mapping_test.cpp +++ b/test/file_mapping_test.cpp @@ -30,6 +30,42 @@ int main () { BOOST_INTERPROCESS_TRY{ const std::size_t FileSize = 99999*2; + { + { + std::ofstream file(get_filename().c_str(), std::ios::binary | std::ios::trunc); + } + { + //Create an empty file mapping + file_mapping mapping(get_filename().c_str(), read_write); + + //Obtain zero file size + offset_t filesize = 5; + if(!mapping.get_size(filesize) || filesize != 0) + return 1; + + //Check mapping of empty file does not work + bool thrown = false; + BOOST_INTERPROCESS_TRY{ + mapped_region region (mapping, read_write); + } + BOOST_INTERPROCESS_CATCH(...){ + thrown = true; + } BOOST_INTERPROCESS_CATCH_END + if(!thrown) + return file_mapping().swap(mapping), file_mapping::remove(get_filename().c_str()), 1; + + thrown = false; + BOOST_INTERPROCESS_TRY{ + mapped_region region (mapping, read_only); + } + BOOST_INTERPROCESS_CATCH(...){ + thrown = true; + } BOOST_INTERPROCESS_CATCH_END + if(!thrown) + return file_mapping().swap(mapping), file_mapping::remove(get_filename().c_str()), 1; + } + file_mapping::remove(get_filename().c_str()); + } { //Create file with given size std::ofstream file(get_filename().c_str(), std::ios::binary | std::ios::trunc); @@ -166,7 +202,7 @@ int main () } BOOST_INTERPROCESS_CATCH(std::exception &exc){ file_mapping::remove(get_filename().c_str()); - std::cout << "Unhandled exception: " << exc.what() << std::endl; + std::cout << "Unexpected Exception: " << exc.what() << std::endl; BOOST_INTERPROCESS_RETHROW } BOOST_INTERPROCESS_CATCH_END file_mapping::remove(get_filename().c_str());