Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-14 08:30:51

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