Skip to content

Commit

Permalink
Define and use DISABLE_BOOST_INTERPROCESS_EINTR_RETRY macro to handle…
Browse files Browse the repository at this point in the history
… EINTR in GCC compatible compilers.
  • Loading branch information
igaztanaga committed Oct 7, 2024
1 parent 3761f39 commit 75c3c9e
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 36 deletions.
61 changes: 33 additions & 28 deletions include/boost/interprocess/detail/os_file_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,24 +509,27 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
inline bool create_directory(const char *path)
{
::mode_t m = ::mode_t(0777);
return ::mkdir(path, m) == 0;
int r = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::mkdir(path, m));
return r == 0;
}

inline bool open_or_create_directory(const char *path)
{
::mode_t m = ::mode_t(0777);
return ::mkdir(path, m) == 0 || (errno == EEXIST);
int r = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::mkdir(path, m));
return r == 0 || (errno == EEXIST);
}

inline bool open_or_create_shared_directory(const char *path)
{
const ::mode_t m = ::mode_t(01777);
const bool created = ::mkdir(path, m) == 0;
int rc = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::mkdir(path, m));
const bool created = rc == 0;
const bool created_or_exists = created || (errno == EEXIST);
//Try to maximize the chance that the sticky bit is set in shared dirs
//created with old versions that did not set it (for security reasons)
const bool chmoded = ::chmod(path, m) == 0;
return created ? chmoded : created_or_exists;
rc = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::chmod(path, m));
return created ? (rc == 0) : created_or_exists;
}

inline bool remove_directory(const char *path)
Expand All @@ -547,9 +550,10 @@ inline file_handle_t create_new_file
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
{
(void)temporary;
int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()));
if(ret >= 0){
::fchmod(ret, perm.get_permissions());
int rc = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fchmod(ret, perm.get_permissions()));
(void)rc;
}
return ret;
}
Expand All @@ -562,13 +566,14 @@ inline file_handle_t create_or_open_file
//We need a loop to change permissions correctly using fchmod, since
//with "O_CREAT only" ::open we don't know if we've created or opened the file.
while(true){
ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()));
if(ret >= 0){
::fchmod(ret, perm.get_permissions());
int rc = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fchmod(ret, perm.get_permissions()));
(void)rc;
break;
}
else if(errno == EEXIST){
if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
if((ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::open(name, (int)mode))) >= 0 || errno != ENOENT){
break;
}
}
Expand All @@ -583,11 +588,11 @@ inline file_handle_t open_existing_file
(const char *name, mode_t mode, bool temporary = false)
{
(void)temporary;
return ::open(name, (int)mode);
return BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::open(name, (int)mode));
}

inline bool delete_file(const char *name)
{ return ::unlink(name) == 0; }
{ return BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::unlink(name)) == 0; }

inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
Expand All @@ -597,30 +602,30 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
errno = EINVAL;
return false;
}
return 0 == ::ftruncate(hnd, off_t(size));
return 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::ftruncate(hnd, off_t(size)));
}

inline bool get_file_size(file_handle_t hnd, offset_t &size)
{
struct stat data;
bool ret = 0 == ::fstat(hnd, &data);
bool ret = 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fstat(hnd, &data));
if(ret){
size = data.st_size;
}
return ret;
}

inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
{ return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
{ return ((off_t)(-1)) != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::lseek(hnd, off, (int)pos)); }

inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
{
off = ::lseek(hnd, 0, SEEK_CUR);
off = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::lseek(hnd, 0, SEEK_CUR));
return off != ((off_t)-1);
}

inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
{ return (ssize_t(numdata)) == ::write(hnd, data, numdata); }
{ return (ssize_t(numdata)) == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::write(hnd, data, numdata)); }

inline file_handle_t invalid_file()
{ return -1; }
Expand All @@ -635,7 +640,7 @@ inline bool acquire_file_lock(file_handle_t hnd)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
return -1 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fcntl(hnd, F_SETLKW, &lock));
}

inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
Expand All @@ -645,7 +650,7 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
int ret = ::fcntl(hnd, F_SETLK, &lock);
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fcntl(hnd, F_SETLK, &lock));
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
(acquired = false, true) : false;
Expand All @@ -660,7 +665,7 @@ inline bool release_file_lock(file_handle_t hnd)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
return -1 != ::fcntl(hnd, F_SETLK, &lock);
return -1 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fcntl(hnd, F_SETLK, &lock));
}

inline bool acquire_file_lock_sharable(file_handle_t hnd)
Expand All @@ -670,7 +675,7 @@ inline bool acquire_file_lock_sharable(file_handle_t hnd)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
return -1 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fcntl(hnd, F_SETLKW, &lock));
}

inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
Expand All @@ -680,7 +685,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
int ret = ::fcntl(hnd, F_SETLK, &lock);
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::fcntl(hnd, F_SETLK, &lock));
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
(acquired = false, true) : false;
Expand All @@ -693,30 +698,30 @@ inline bool release_file_lock_sharable(file_handle_t hnd)

#if 0
inline bool acquire_file_lock(file_handle_t hnd)
{ return 0 == ::flock(hnd, LOCK_EX); }
{ return 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_EX)); }

inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
{
int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_EX | LOCK_NB));
acquired = ret == 0;
return (acquired || errno == EWOULDBLOCK);
}

inline bool release_file_lock(file_handle_t hnd)
{ return 0 == ::flock(hnd, LOCK_UN); }
{ return 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_UN)); }

inline bool acquire_file_lock_sharable(file_handle_t hnd)
{ return 0 == ::flock(hnd, LOCK_SH); }
{ return 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_SH)); }

inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
{
int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_SH | LOCK_NB));
acquired = ret == 0;
return (acquired || errno == EWOULDBLOCK);
}

inline bool release_file_lock_sharable(file_handle_t hnd)
{ return 0 == ::flock(hnd, LOCK_UN); }
{ return 0 == BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::flock(hnd, LOCK_UN)); }
#endif

inline bool delete_subdirectories_recursive
Expand Down
4 changes: 2 additions & 2 deletions include/boost/interprocess/detail/os_thread_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ inline void thread_sleep_tick()
rqt.tv_nsec = (long)get_system_tick_ns()/2;

struct timespec rmn;
while (0 != ::nanosleep(&rqt, &rmn) && errno == EINTR) {
while (0 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::nanosleep(&rqt, &rmn)) && errno == EINTR) {
rqt.tv_sec = rmn.tv_sec;
rqt.tv_nsec = rmn.tv_nsec;
}
Expand All @@ -454,7 +454,7 @@ inline void thread_sleep_ms(unsigned int ms)
rqt.tv_nsec = static_cast<long int>((ms%1000u)*1000000u);

struct timespec rmn;
while (0 != ::nanosleep(&rqt, &rmn) && errno == EINTR) {
while (0 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::nanosleep(&rqt, &rmn)) && errno == EINTR) {
rqt.tv_sec = rmn.tv_sec;
rqt.tv_nsec = rmn.tv_nsec;
}
Expand Down
24 changes: 24 additions & 0 deletions include/boost/interprocess/detail/workaround.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,28 @@ namespace boost {
#define BOOST_INTERPROCESS_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED
#endif


////////////////////////////////////////////
//
// BOOST_INTERPROCESS_EINTR_RETRY
//
////////////////////////////////////////////

//#define DISABLE_BOOST_INTERPROCESS_EINTR_RETRY
#if !defined(DISABLE_BOOST_INTERPROCESS_EINTR_RETRY) && defined(__GNUC__)

/* taken from glibc unistd.h and fixes musl */
#define BOOST_INTERPROCESS_EINTR_RETRY(RESULTTYPE, FAILUREVALUE, EXPRESSION) \
(__extension__ \
({ RESULTTYPE __result; \
do __result = (RESULTTYPE) (EXPRESSION); \
while (__result == FAILUREVALUE && errno == EINTR); \
__result; }))

#else //!defined(DISABLE_BOOST_INTERPROCESS_EINTR_RETRY) && defined(__GNUC__)

#define BOOST_INTERPROCESS_EINTR_RETRY(RESULTTYPE, FAILUREVALUE, EXPRESSION) ((RESULTTYPE)(EXPRESSION))

#endif //!defined(DISABLE_BOOST_INTERPROCESS_EINTR_RETRY) && defined(__GNUC__)

#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
16 changes: 10 additions & 6 deletions include/boost/interprocess/sync/posix/semaphore_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,27 @@ inline bool semaphore_open
case DoOpen:
{
//No addition
handle = ::sem_open(name.c_str(), oflag);
handle = BOOST_INTERPROCESS_EINTR_RETRY(sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED, ::sem_open(name.c_str(), oflag));
}
break;
case DoOpenOrCreate:
case DoCreate:
{
while(1){
oflag = (O_CREAT | O_EXCL);
handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count);
handle = BOOST_INTERPROCESS_EINTR_RETRY
( sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED
, ::sem_open(name.c_str(), oflag, perm.get_permissions(), count));
if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
//We can't change semaphore permissions!
//::fchmod(handle, perm.get_permissions());
break;
}
else if(errno == EEXIST && type == DoOpenOrCreate){
oflag = 0;
if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
if( (handle = BOOST_INTERPROCESS_EINTR_RETRY
(sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED, ::sem_open(name.c_str(), oflag)))
!= BOOST_INTERPROCESS_POSIX_SEM_FAILED
|| (errno != ENOENT) ){
break;
}
Expand Down Expand Up @@ -177,7 +181,7 @@ inline void semaphore_post(sem_t *handle)

inline void semaphore_wait(sem_t *handle)
{
int ret = sem_wait(handle);
int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_wait(handle));
if(ret != 0){
error_info err = system_error_code();
throw interprocess_exception(err);
Expand All @@ -186,7 +190,7 @@ inline void semaphore_wait(sem_t *handle)

inline bool semaphore_try_wait(sem_t *handle)
{
int res = sem_trywait(handle);
int res = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_trywait(handle));
if(res == 0)
return true;
if(system_error_code() == EAGAIN){
Expand Down Expand Up @@ -228,7 +232,7 @@ inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time)

timespec tspec = timepoint_to_timespec(abs_time);
for (;;){
int res = sem_timedwait(handle, &tspec);
int res = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_timedwait(handle, &tspec));
if(res == 0)
return true;
if (res > 0){
Expand Down

0 comments on commit 75c3c9e

Please sign in to comment.