From 75c3c9ef0a3d8ae2cd90bbf3af438a13913319cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 8 Oct 2024 00:06:02 +0200 Subject: [PATCH] Define and use DISABLE_BOOST_INTERPROCESS_EINTR_RETRY macro to handle EINTR in GCC compatible compilers. --- .../interprocess/detail/os_file_functions.hpp | 61 ++++++++++--------- .../detail/os_thread_functions.hpp | 4 +- .../boost/interprocess/detail/workaround.hpp | 24 ++++++++ .../sync/posix/semaphore_wrapper.hpp | 16 +++-- 4 files changed, 69 insertions(+), 36 deletions(-) diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index 1ec3b831..137409da 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -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) @@ -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; } @@ -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; } } @@ -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) { @@ -597,13 +602,13 @@ 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; } @@ -611,16 +616,16 @@ inline bool get_file_size(file_handle_t hnd, offset_t &size) } 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; } @@ -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) @@ -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; @@ -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) @@ -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) @@ -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; @@ -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 diff --git a/include/boost/interprocess/detail/os_thread_functions.hpp b/include/boost/interprocess/detail/os_thread_functions.hpp index 15421981..deb8eef2 100644 --- a/include/boost/interprocess/detail/os_thread_functions.hpp +++ b/include/boost/interprocess/detail/os_thread_functions.hpp @@ -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; } @@ -454,7 +454,7 @@ inline void thread_sleep_ms(unsigned int ms) rqt.tv_nsec = static_cast((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; } diff --git a/include/boost/interprocess/detail/workaround.hpp b/include/boost/interprocess/detail/workaround.hpp index 02528ce0..af044b7c 100644 --- a/include/boost/interprocess/detail/workaround.hpp +++ b/include/boost/interprocess/detail/workaround.hpp @@ -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 diff --git a/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp index 30c0bbb3..86c6ad1f 100644 --- a/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ b/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -70,7 +70,7 @@ 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: @@ -78,7 +78,9 @@ inline bool semaphore_open { 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()); @@ -86,7 +88,9 @@ inline bool semaphore_open } 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; } @@ -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); @@ -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){ @@ -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){