File indexing completed on 2025-01-18 09:38:35
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 #endif
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
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
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
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
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
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 }
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
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
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
0392
0393 while(true){
0394
0395 m_handle = shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
0396
0397 if(m_handle >= 0){
0398 ::fchmod(m_handle, unix_perm);
0399 }
0400
0401 else if(errno == EEXIST){
0402 m_handle = shm_open(fname.c_str(), oflag, unix_perm);
0403
0404
0405 if(m_handle < 0 && errno == ENOENT){
0406 continue;
0407 }
0408 }
0409
0410 break;
0411 }
0412 }
0413 break;
0414 default:
0415 {
0416 error_info err = other_error;
0417 throw interprocess_exception(err);
0418 }
0419 }
0420
0421
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
0470 #endif
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
0492
0493
0494
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
0508
0509 }
0510 }
0511
0512 #include <boost/interprocess/detail/config_end.hpp>
0513
0514 #endif