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