File indexing completed on 2026-05-10 08:23:29
0001
0002
0003
0004
0005
0006
0007
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
0053
0054
0055 namespace boost {
0056 namespace interprocess {
0057
0058
0059
0060 class shared_memory_object
0061 {
0062 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0063
0064 BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_memory_object)
0065 #endif
0066
0067 public:
0068
0069 shared_memory_object() BOOST_NOEXCEPT;
0070
0071
0072
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
0077
0078
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
0083
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
0090
0091
0092
0093
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
0098
0099
0100
0101
0102
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
0107
0108
0109
0110
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
0115
0116
0117
0118
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
0125
0126
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
0135 void swap(shared_memory_object &moved) BOOST_NOEXCEPT;
0136
0137
0138
0139 static bool remove(const char *name);
0140
0141 #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0142
0143
0144
0145
0146
0147
0148 static bool remove(const wchar_t *name);
0149
0150 #endif
0151
0152
0153 void truncate(offset_t length);
0154
0155
0156
0157
0158
0159
0160
0161
0162 ~shared_memory_object();
0163
0164
0165 const char *get_name() const BOOST_NOEXCEPT;
0166
0167
0168
0169 bool get_size(offset_t &size) const BOOST_NOEXCEPT;
0170
0171
0172 mode_t get_mode() const BOOST_NOEXCEPT;
0173
0174
0175 mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT;
0176
0177 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0178 private:
0179
0180
0181 void priv_close();
0182
0183
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
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
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
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
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
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
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 }
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
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
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
0398
0399 while(true){
0400
0401 m_handle = eintr_aware_shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
0402
0403 if(m_handle >= 0){
0404 ::fchmod(m_handle, unix_perm);
0405 }
0406
0407 else if(errno == EEXIST){
0408 m_handle = eintr_aware_shm_open(fname.c_str(), oflag, unix_perm);
0409
0410
0411 if(m_handle < 0 && errno == ENOENT){
0412 continue;
0413 }
0414 }
0415
0416 break;
0417 }
0418 }
0419 break;
0420 default:
0421 {
0422 error_info err = other_error;
0423 throw interprocess_exception(err);
0424 }
0425 }
0426
0427
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
0476 #endif
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
0507
0508
0509
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
0523
0524 }
0525 }
0526
0527 #include <boost/interprocess/detail/config_end.hpp>
0528
0529 #endif