Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:23:29

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
0012 #define BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 0018 ">#
0019 #if defined(BOOST_HAS_PRAGMA_ONCE)
0020 #  pragma once
0021 #endif
0022 
0023 #include <boost/interprocess/detail/config_begin.hpp>
0024 #include <boost/interprocess/detail/workaround.hpp>
0025 #include <boost/interprocess/creation_tags.hpp>
0026 #include <boost/interprocess/exceptions.hpp>
0027 #include <boost/move/utility_core.hpp>
0028 #include <boost/interprocess/interprocess_fwd.hpp>
0029 #include <boost/interprocess/exceptions.hpp>
0030 #include <boost/interprocess/detail/os_file_functions.hpp>
0031 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
0032 #include <boost/interprocess/detail/char_wchar_holder.hpp>
0033 #include <boost/interprocess/permissions.hpp>
0034 #include <boost/move/adl_move_swap.hpp>
0035 #include <cstddef>
0036 
0037 #if defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
0038 #  include <string>
0039 #  include <fcntl.h>        //posix_fallocate, O_CREAT, O_*...
0040 #  include <sys/mman.h>     //shm_xxx
0041 #  include <unistd.h>       //ftruncate, close
0042 #  include <sys/stat.h>     //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
0043 #  if defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0044 #     if defined(__FreeBSD__)
0045 #        include <sys/sysctl.h>
0046 #     endif
0047 #  endif
0048 #else
0049 //
0050 #endif
0051 
0052 //!\file
0053 //!Describes a shared memory object management class.
0054 
0055 namespace boost {
0056 namespace interprocess {
0057 
0058 //!A class that wraps a shared memory mapping that can be used to
0059 //!create mapped regions from the mapped files
0060 class shared_memory_object
0061 {
0062    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0063    //Non-copyable and non-assignable
0064    BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_memory_object)
0065    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0066 
0067    public:
0068    //!Default constructor. Represents an empty shared_memory_object.
0069    shared_memory_object() BOOST_NOEXCEPT;
0070 
0071    //!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
0072    //!If the file previously exists, throws an error.*/
0073    shared_memory_object(create_only_t, const char *name, mode_t mode, const permissions &perm = permissions())
0074    {  this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm);  }
0075 
0076    //!Tries to create a shared memory object with name "name" and mode "mode", with the
0077    //!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
0078    //!Otherwise throws an error.
0079    shared_memory_object(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions())
0080    {  this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm);  }
0081 
0082    //!Tries to open a shared memory object with name "name", with the access mode "mode".
0083    //!If the file does not previously exist, it throws an error.
0084    shared_memory_object(open_only_t, const char *name, mode_t mode)
0085    {  this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions());  }
0086 
0087    #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0088 
0089    //!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
0090    //!If the file previously exists, throws an error.
0091    //! 
0092    //!Note: This function is only available on operating systems with
0093    //!      native wchar_t APIs (e.g. Windows).
0094    shared_memory_object(create_only_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
0095    {  this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm);  }
0096 
0097    //!Tries to create a shared memory object with name "name" and mode "mode", with the
0098    //!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
0099    //!Otherwise throws an error.
0100    //! 
0101    //!Note: This function is only available on operating systems with
0102    //!      native wchar_t APIs (e.g. Windows).
0103    shared_memory_object(open_or_create_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
0104    {  this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm);  }
0105 
0106    //!Tries to open a shared memory object with name "name", with the access mode "mode".
0107    //!If the file does not previously exist, it throws an error.
0108    //! 
0109    //!Note: This function is only available on operating systems with
0110    //!      native wchar_t APIs (e.g. Windows).
0111    shared_memory_object(open_only_t, const wchar_t*name, mode_t mode)
0112    {  this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions());  }
0113 
0114    #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0115 
0116    //!Moves the ownership of "moved"'s shared memory object to *this.
0117    //!After the call, "moved" does not represent any shared memory object.
0118    //!Does not throw
0119    shared_memory_object(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
0120       :  m_handle(file_handle_t(ipcdetail::invalid_file()))
0121       ,  m_mode(read_only)
0122    {  this->swap(moved);   }
0123 
0124    //!Moves the ownership of "moved"'s shared memory to *this.
0125    //!After the call, "moved" does not represent any shared memory.
0126    //!Does not throw
0127    shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
0128    {
0129       shared_memory_object tmp(boost::move(moved));
0130       this->swap(tmp);
0131       return *this;
0132    }
0133 
0134    //!Swaps the shared_memory_objects. Does not throw
0135    void swap(shared_memory_object &moved) BOOST_NOEXCEPT;
0136 
0137    //!Erases a shared memory object from the system.
0138    //!Returns false on error. Never throws
0139    static bool remove(const char *name);
0140 
0141    #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0142 
0143    //!Erases a shared memory object from the system.
0144    //!Returns false on error. Never throws
0145    //! 
0146    //!Note: This function is only available on operating systems with
0147    //!      native wchar_t APIs (e.g. Windows).
0148    static bool remove(const wchar_t *name);
0149 
0150    #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0151 
0152    //!Sets the size of the shared memory mapping
0153    void truncate(offset_t length);
0154 
0155    //!Destroys *this and indicates that the calling process is finished using
0156    //!the resource. All mapped regions are still
0157    //!valid after destruction. The destructor function will deallocate
0158    //!any system resources allocated by the system for use by this process for
0159    //!this resource. The resource can still be opened again calling
0160    //!the open constructor overload. To erase the resource from the system
0161    //!use remove().
0162    ~shared_memory_object();
0163 
0164    //!Returns the name of the shared memory object.
0165    const char *get_name() const BOOST_NOEXCEPT;
0166 
0167    //!Returns true if the size of the shared memory object
0168    //!can be obtained and writes the size in the passed reference
0169    bool get_size(offset_t &size) const BOOST_NOEXCEPT;
0170 
0171    //!Returns access mode
0172    mode_t get_mode() const BOOST_NOEXCEPT;
0173 
0174    //!Returns mapping handle. Never throws.
0175    mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT;
0176 
0177    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0178    private:
0179 
0180    //!Closes a previously opened file mapping. Never throws.
0181    void priv_close();
0182 
0183    //!Opens or creates a shared memory object.
0184    template<class CharT>
0185    bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm);
0186 
0187    file_handle_t     m_handle;
0188    mode_t            m_mode;
0189    char_wchar_holder m_filename;
0190 
0191    #ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
0192    static int eintr_aware_shm_open(const char* name, int oflag, ::mode_t mode);
0193    #endif
0194 
0195    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0196 };
0197 
0198 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0199 
0200 inline shared_memory_object::shared_memory_object() BOOST_NOEXCEPT
0201    :  m_handle(file_handle_t(ipcdetail::invalid_file()))
0202    ,  m_mode(read_only)
0203 {}
0204 
0205 inline shared_memory_object::~shared_memory_object()
0206 {  this->priv_close(); }
0207 
0208 
0209 inline const char *shared_memory_object::get_name() const BOOST_NOEXCEPT
0210 {  return m_filename.getn(); }
0211 
0212 inline bool shared_memory_object::get_size(offset_t &size) const BOOST_NOEXCEPT
0213 {  return ipcdetail::get_file_size((file_handle_t)m_handle, size);  }
0214 
0215 inline void shared_memory_object::swap(shared_memory_object &other) BOOST_NOEXCEPT
0216 {
0217    boost::adl_move_swap(m_handle, other.m_handle);
0218    boost::adl_move_swap(m_mode,   other.m_mode);
0219    m_filename.swap(other.m_filename);
0220 }
0221 
0222 inline mapping_handle_t shared_memory_object::get_mapping_handle() const BOOST_NOEXCEPT
0223 {
0224    return ipcdetail::mapping_handle_from_file_handle(m_handle);
0225 }
0226 
0227 inline mode_t shared_memory_object::get_mode() const BOOST_NOEXCEPT
0228 {  return m_mode; }
0229 
0230 #if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
0231 
0232 template<class CharT>
0233 inline bool shared_memory_object::priv_open_or_create
0234    (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm)
0235 {
0236    m_filename = filename;
0237    std::basic_string<CharT> shmfile;
0238    ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile);
0239 
0240    //Set accesses
0241    if (mode != read_write && mode != read_only){
0242       error_info err = other_error;
0243       throw interprocess_exception(err);
0244    }
0245 
0246    switch(type){
0247       case ipcdetail::DoOpen:
0248          m_handle = ipcdetail::open_existing_file(shmfile.c_str(), mode, true);
0249       break;
0250       case ipcdetail::DoCreate:
0251          m_handle = ipcdetail::create_new_file(shmfile.c_str(), mode, perm, true);
0252       break;
0253       case ipcdetail::DoOpenOrCreate:
0254          m_handle = ipcdetail::create_or_open_file(shmfile.c_str(), mode, perm, true);
0255       break;
0256       default:
0257          {
0258             error_info err = other_error;
0259             throw interprocess_exception(err);
0260          }
0261    }
0262 
0263    //Check for error
0264    if(m_handle == ipcdetail::invalid_file()){
0265       error_info err = system_error_code();
0266       this->priv_close();
0267       throw interprocess_exception(err);
0268    }
0269 
0270    m_mode = mode;
0271    return true;
0272 }
0273 
0274 #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES)
0275 
0276 inline bool shared_memory_object::remove(const wchar_t *filename)
0277 {
0278    BOOST_INTERPROCESS_TRY{
0279       //Make sure a temporary path is created for shared memory
0280       std::wstring shmfile;
0281       ipcdetail::shared_filepath(filename, shmfile);
0282       return ipcdetail::delete_file(shmfile.c_str());
0283    }
0284    BOOST_INTERPROCESS_CATCH(...){
0285       return false;
0286    } BOOST_INTERPROCESS_CATCH_END
0287 }
0288 
0289 #endif
0290 
0291 inline bool shared_memory_object::remove(const char *filename)
0292 {
0293    BOOST_INTERPROCESS_TRY{
0294       //Make sure a temporary path is created for shared memory
0295       std::string shmfile;
0296       ipcdetail::shared_filepath(filename, shmfile);
0297       return ipcdetail::delete_file(shmfile.c_str());
0298    }
0299    BOOST_INTERPROCESS_CATCH(...){
0300       return false;
0301    } BOOST_INTERPROCESS_CATCH_END
0302 }
0303 
0304 inline void shared_memory_object::truncate(offset_t length)
0305 {
0306    if(!ipcdetail::truncate_file(m_handle, (std::size_t)length)){
0307       error_info err = system_error_code();
0308       throw interprocess_exception(err);
0309    }
0310 }
0311 
0312 inline void shared_memory_object::priv_close()
0313 {
0314    if(m_handle != ipcdetail::invalid_file()){
0315       ipcdetail::close_file(m_handle);
0316       m_handle = ipcdetail::invalid_file();
0317    }
0318 }
0319 
0320 #else //!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
0321 
0322 namespace shared_memory_object_detail {
0323 
0324 #ifdef BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
0325 
0326 #if defined(__FreeBSD__)
0327 
0328 inline bool use_filesystem_based_posix()
0329 {
0330    int jailed = 0;
0331    std::size_t len = sizeof(jailed);
0332    ::sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0);
0333    return jailed != 0;
0334 }
0335 
0336 #else
0337 #error "Not supported platform for BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY"
0338 #endif
0339 
0340 #endif
0341 
0342 }  //shared_memory_object_detail
0343 
0344 template<class CharT>
0345 inline bool shared_memory_object::priv_open_or_create
0346    (ipcdetail::create_enum_t type,
0347     const CharT *filename,
0348     mode_t mode, const permissions &perm)
0349 {
0350    #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0351    const bool add_leading_slash = false;
0352    #elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0353    const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
0354    #else
0355    const bool add_leading_slash = true;
0356    #endif
0357    std::basic_string<CharT> fname;
0358    if(add_leading_slash){
0359       ipcdetail::add_leading_slash(filename, fname);
0360    }
0361    else{
0362       ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, fname);
0363    }
0364 
0365    //Create new mapping
0366    int oflag = 0;
0367    if(mode == read_only){
0368       oflag |= O_RDONLY;
0369    }
0370    else if(mode == read_write){
0371       oflag |= O_RDWR;
0372    }
0373    else{
0374       error_info err(mode_error);
0375       throw interprocess_exception(err);
0376    }
0377    ::mode_t unix_perm = perm.get_permissions();
0378 
0379    switch(type){
0380       case ipcdetail::DoOpen:
0381       {
0382          //No oflag addition
0383          m_handle = eintr_aware_shm_open(fname.c_str(), oflag, unix_perm);
0384       }
0385       break;
0386       case ipcdetail::DoCreate:
0387       {
0388          oflag |= (O_CREAT | O_EXCL);
0389          m_handle = eintr_aware_shm_open(fname.c_str(), oflag, unix_perm);
0390          if(m_handle >= 0){
0391             ::fchmod(m_handle, unix_perm);
0392          }
0393       }
0394       break;
0395       case ipcdetail::DoOpenOrCreate:
0396       {
0397          //We need a create/open loop to change permissions correctly using fchmod, since
0398          //with "O_CREAT" only we don't know if we've created or opened the shm.
0399          while(true){
0400             //Try to create shared memory
0401             m_handle = eintr_aware_shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
0402             //If successful change real permissions
0403             if(m_handle >= 0){
0404                ::fchmod(m_handle, unix_perm);
0405             }
0406             //If already exists, try to open
0407             else if(errno == EEXIST){
0408                m_handle = eintr_aware_shm_open(fname.c_str(), oflag, unix_perm);
0409                //If open fails and errno tells the file does not exist
0410                //(shm was removed between creation and opening tries), just retry
0411                if(m_handle < 0 && errno == ENOENT){
0412                   continue;
0413                }
0414             }
0415             //Exit retries
0416             break;
0417          }
0418       }
0419       break;
0420       default:
0421       {
0422          error_info err = other_error;
0423          throw interprocess_exception(err);
0424       }
0425    }
0426 
0427    //Check for error
0428    if(m_handle < 0){
0429       error_info err = errno;
0430       this->priv_close();
0431       throw interprocess_exception(err);
0432    }
0433 
0434    m_filename = filename;
0435    m_mode = mode;
0436    return true;
0437 }
0438 
0439 inline bool shared_memory_object::remove(const char *filename)
0440 {
0441    BOOST_INTERPROCESS_TRY{
0442       std::string filepath;
0443       #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0444       const bool add_leading_slash = false;
0445       #elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0446       const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
0447       #else
0448       const bool add_leading_slash = true;
0449       #endif
0450       if(add_leading_slash){
0451          ipcdetail::add_leading_slash(filename, filepath);
0452       }
0453       else{
0454          ipcdetail::shared_filepath(filename, filepath);
0455       }
0456       return 0 == shm_unlink(filepath.c_str());
0457    }
0458    BOOST_INTERPROCESS_CATCH(...){
0459       return false;
0460    } BOOST_INTERPROCESS_CATCH_END
0461 }
0462 
0463 inline void shared_memory_object::truncate(offset_t length)
0464 {
0465    #ifdef BOOST_INTERPROCESS_POSIX_FALLOCATE
0466    int ret = EINTR;
0467    while (EINTR == ret) {
0468       ret = posix_fallocate(m_handle, 0, length);
0469    }
0470 
0471    if (ret && ret != EOPNOTSUPP && ret != ENODEV){
0472       error_info err(ret);
0473       throw interprocess_exception(err);
0474    }
0475    //ftruncate fallback
0476    #endif //BOOST_INTERPROCESS_POSIX_FALLOCATE
0477 
0478    handle_eintr:
0479    if (0 != ftruncate(m_handle, length)){
0480       if (errno == EINTR)
0481          goto handle_eintr;
0482       error_info err(system_error_code());
0483       throw interprocess_exception(err);
0484    }
0485 }
0486 
0487 inline void shared_memory_object::priv_close()
0488 {
0489    if(m_handle != -1){
0490       ::close(m_handle);
0491       m_handle = -1;
0492    }
0493 }
0494 
0495 inline int shared_memory_object::eintr_aware_shm_open(const char* name, int oflag, ::mode_t mode)
0496 {
0497    int shm_open_ret;
0498    do {
0499       shm_open_ret = shm_open(name, oflag, mode);
0500    } while (shm_open_ret == -1 && errno == EINTR);
0501    return shm_open_ret;
0502 }
0503 
0504 #endif
0505 
0506 //!A class that stores the name of a shared memory
0507 //!and calls shared_memory_object::remove(name) in its destructor
0508 //!Useful to remove temporary shared memory objects in the presence
0509 //!of exceptions
0510 class remove_shared_memory_on_destroy
0511 {
0512    const char * m_name;
0513    public:
0514    remove_shared_memory_on_destroy(const char *name)
0515       :  m_name(name)
0516    {}
0517 
0518    ~remove_shared_memory_on_destroy()
0519    {  shared_memory_object::remove(m_name);  }
0520 };
0521 
0522 #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0523 
0524 }  //namespace interprocess {
0525 }  //namespace boost {
0526 
0527 #include <boost/interprocess/detail/config_end.hpp>
0528 
0529 #endif   //BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP