Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:35

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    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0190 };
0191 
0192 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0193 
0194 inline shared_memory_object::shared_memory_object() BOOST_NOEXCEPT
0195    :  m_handle(file_handle_t(ipcdetail::invalid_file()))
0196    ,  m_mode(read_only)
0197 {}
0198 
0199 inline shared_memory_object::~shared_memory_object()
0200 {  this->priv_close(); }
0201 
0202 
0203 inline const char *shared_memory_object::get_name() const BOOST_NOEXCEPT
0204 {  return m_filename.getn(); }
0205 
0206 inline bool shared_memory_object::get_size(offset_t &size) const BOOST_NOEXCEPT
0207 {  return ipcdetail::get_file_size((file_handle_t)m_handle, size);  }
0208 
0209 inline void shared_memory_object::swap(shared_memory_object &other) BOOST_NOEXCEPT
0210 {
0211    boost::adl_move_swap(m_handle, other.m_handle);
0212    boost::adl_move_swap(m_mode,   other.m_mode);
0213    m_filename.swap(other.m_filename);
0214 }
0215 
0216 inline mapping_handle_t shared_memory_object::get_mapping_handle() const BOOST_NOEXCEPT
0217 {
0218    return ipcdetail::mapping_handle_from_file_handle(m_handle);
0219 }
0220 
0221 inline mode_t shared_memory_object::get_mode() const BOOST_NOEXCEPT
0222 {  return m_mode; }
0223 
0224 #if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
0225 
0226 template<class CharT>
0227 inline bool shared_memory_object::priv_open_or_create
0228    (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm)
0229 {
0230    m_filename = filename;
0231    std::basic_string<CharT> shmfile;
0232    ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile);
0233 
0234    //Set accesses
0235    if (mode != read_write && mode != read_only){
0236       error_info err = other_error;
0237       throw interprocess_exception(err);
0238    }
0239 
0240    switch(type){
0241       case ipcdetail::DoOpen:
0242          m_handle = ipcdetail::open_existing_file(shmfile.c_str(), mode, true);
0243       break;
0244       case ipcdetail::DoCreate:
0245          m_handle = ipcdetail::create_new_file(shmfile.c_str(), mode, perm, true);
0246       break;
0247       case ipcdetail::DoOpenOrCreate:
0248          m_handle = ipcdetail::create_or_open_file(shmfile.c_str(), mode, perm, true);
0249       break;
0250       default:
0251          {
0252             error_info err = other_error;
0253             throw interprocess_exception(err);
0254          }
0255    }
0256 
0257    //Check for error
0258    if(m_handle == ipcdetail::invalid_file()){
0259       error_info err = system_error_code();
0260       this->priv_close();
0261       throw interprocess_exception(err);
0262    }
0263 
0264    m_mode = mode;
0265    return true;
0266 }
0267 
0268 #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES)
0269 
0270 inline bool shared_memory_object::remove(const wchar_t *filename)
0271 {
0272    BOOST_TRY{
0273       //Make sure a temporary path is created for shared memory
0274       std::wstring shmfile;
0275       ipcdetail::shared_filepath(filename, shmfile);
0276       return ipcdetail::delete_file(shmfile.c_str());
0277    }
0278    BOOST_CATCH(...){
0279       return false;
0280    } BOOST_CATCH_END
0281 }
0282 
0283 #endif
0284 
0285 inline bool shared_memory_object::remove(const char *filename)
0286 {
0287    BOOST_TRY{
0288       //Make sure a temporary path is created for shared memory
0289       std::string shmfile;
0290       ipcdetail::shared_filepath(filename, shmfile);
0291       return ipcdetail::delete_file(shmfile.c_str());
0292    }
0293    BOOST_CATCH(...){
0294       return false;
0295    } BOOST_CATCH_END
0296 }
0297 
0298 inline void shared_memory_object::truncate(offset_t length)
0299 {
0300    if(!ipcdetail::truncate_file(m_handle, (std::size_t)length)){
0301       error_info err = system_error_code();
0302       throw interprocess_exception(err);
0303    }
0304 }
0305 
0306 inline void shared_memory_object::priv_close()
0307 {
0308    if(m_handle != ipcdetail::invalid_file()){
0309       ipcdetail::close_file(m_handle);
0310       m_handle = ipcdetail::invalid_file();
0311    }
0312 }
0313 
0314 #else //!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
0315 
0316 namespace shared_memory_object_detail {
0317 
0318 #ifdef BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
0319 
0320 #if defined(__FreeBSD__)
0321 
0322 inline bool use_filesystem_based_posix()
0323 {
0324    int jailed = 0;
0325    std::size_t len = sizeof(jailed);
0326    ::sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0);
0327    return jailed != 0;
0328 }
0329 
0330 #else
0331 #error "Not supported platform for BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY"
0332 #endif
0333 
0334 #endif
0335 
0336 }  //shared_memory_object_detail
0337 
0338 template<class CharT>
0339 inline bool shared_memory_object::priv_open_or_create
0340    (ipcdetail::create_enum_t type,
0341     const CharT *filename,
0342     mode_t mode, const permissions &perm)
0343 {
0344    #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0345    const bool add_leading_slash = false;
0346    #elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0347    const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
0348    #else
0349    const bool add_leading_slash = true;
0350    #endif
0351    std::basic_string<CharT> fname;
0352    if(add_leading_slash){
0353       ipcdetail::add_leading_slash(filename, fname);
0354    }
0355    else{
0356       ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, fname);
0357    }
0358 
0359    //Create new mapping
0360    int oflag = 0;
0361    if(mode == read_only){
0362       oflag |= O_RDONLY;
0363    }
0364    else if(mode == read_write){
0365       oflag |= O_RDWR;
0366    }
0367    else{
0368       error_info err(mode_error);
0369       throw interprocess_exception(err);
0370    }
0371    ::mode_t unix_perm = perm.get_permissions();
0372 
0373    switch(type){
0374       case ipcdetail::DoOpen:
0375       {
0376          //No oflag addition
0377          m_handle = shm_open(fname.c_str(), oflag, unix_perm);
0378       }
0379       break;
0380       case ipcdetail::DoCreate:
0381       {
0382          oflag |= (O_CREAT | O_EXCL);
0383          m_handle = shm_open(fname.c_str(), oflag, unix_perm);
0384          if(m_handle >= 0){
0385             ::fchmod(m_handle, unix_perm);
0386          }
0387       }
0388       break;
0389       case ipcdetail::DoOpenOrCreate:
0390       {
0391          //We need a create/open loop to change permissions correctly using fchmod, since
0392          //with "O_CREAT" only we don't know if we've created or opened the shm.
0393          while(true){
0394             //Try to create shared memory
0395             m_handle = shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
0396             //If successful change real permissions
0397             if(m_handle >= 0){
0398                ::fchmod(m_handle, unix_perm);
0399             }
0400             //If already exists, try to open
0401             else if(errno == EEXIST){
0402                m_handle = shm_open(fname.c_str(), oflag, unix_perm);
0403                //If open fails and errno tells the file does not exist
0404                //(shm was removed between creation and opening tries), just retry
0405                if(m_handle < 0 && errno == ENOENT){
0406                   continue;
0407                }
0408             }
0409             //Exit retries
0410             break;
0411          }
0412       }
0413       break;
0414       default:
0415       {
0416          error_info err = other_error;
0417          throw interprocess_exception(err);
0418       }
0419    }
0420 
0421    //Check for error
0422    if(m_handle < 0){
0423       error_info err = errno;
0424       this->priv_close();
0425       throw interprocess_exception(err);
0426    }
0427 
0428    m_filename = filename;
0429    m_mode = mode;
0430    return true;
0431 }
0432 
0433 inline bool shared_memory_object::remove(const char *filename)
0434 {
0435    BOOST_TRY{
0436       std::string filepath;
0437       #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0438       const bool add_leading_slash = false;
0439       #elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
0440       const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
0441       #else
0442       const bool add_leading_slash = true;
0443       #endif
0444       if(add_leading_slash){
0445          ipcdetail::add_leading_slash(filename, filepath);
0446       }
0447       else{
0448          ipcdetail::shared_filepath(filename, filepath);
0449       }
0450       return 0 == shm_unlink(filepath.c_str());
0451    }
0452    BOOST_CATCH(...){
0453       return false;
0454    } BOOST_CATCH_END
0455 }
0456 
0457 inline void shared_memory_object::truncate(offset_t length)
0458 {
0459    #ifdef BOOST_INTERPROCESS_POSIX_FALLOCATE
0460    int ret = EINTR;
0461    while (EINTR == ret) {
0462       ret = posix_fallocate(m_handle, 0, length);
0463    }
0464 
0465    if (ret && ret != EOPNOTSUPP && ret != ENODEV){
0466       error_info err(ret);
0467       throw interprocess_exception(err);
0468    }
0469    //ftruncate fallback
0470    #endif //BOOST_INTERPROCESS_POSIX_FALLOCATE
0471 
0472    handle_eintr:
0473    if (0 != ftruncate(m_handle, length)){
0474       if (errno == EINTR)
0475          goto handle_eintr;
0476       error_info err(system_error_code());
0477       throw interprocess_exception(err);
0478    }
0479 }
0480 
0481 inline void shared_memory_object::priv_close()
0482 {
0483    if(m_handle != -1){
0484       ::close(m_handle);
0485       m_handle = -1;
0486    }
0487 }
0488 
0489 #endif
0490 
0491 //!A class that stores the name of a shared memory
0492 //!and calls shared_memory_object::remove(name) in its destructor
0493 //!Useful to remove temporary shared memory objects in the presence
0494 //!of exceptions
0495 class remove_shared_memory_on_destroy
0496 {
0497    const char * m_name;
0498    public:
0499    remove_shared_memory_on_destroy(const char *name)
0500       :  m_name(name)
0501    {}
0502 
0503    ~remove_shared_memory_on_destroy()
0504    {  shared_memory_object::remove(m_name);  }
0505 };
0506 
0507 #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0508 
0509 }  //namespace interprocess {
0510 }  //namespace boost {
0511 
0512 #include <boost/interprocess/detail/config_end.hpp>
0513 
0514 #endif   //BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP