From 9993dfafa278f314088930cff70ffdd8de94562a Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 21 Mar 2022 13:25:55 +0100 Subject: [PATCH] Implemented exponential backoff for shared memory related waits --- lib/shared_memory.cpp | 16 ++++++++-------- lib/util.cpp | 15 +++++++++++++++ lib/util.h | 2 ++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/shared_memory.cpp b/lib/shared_memory.cpp index 272a132c..0cc78f19 100644 --- a/lib/shared_memory.cpp +++ b/lib/shared_memory.cpp @@ -100,7 +100,7 @@ namespace IPC{ } if (!(*this)){ if (GetLastError() == ERROR_FILE_NOT_FOUND && !noWait){// Error code 2 - Util::wait(500); + Util::wait(Util::expBackoffMs(timer-1, 10, 5000)); }else{ break; } @@ -121,7 +121,7 @@ namespace IPC{ } if (!(*this)){ if (errno == ENOENT && !noWait){ - Util::wait(500); + Util::wait(Util::expBackoffMs(timer-1, 10, 5000)); }else{ break; } @@ -458,10 +458,10 @@ namespace IPC{ }else{ int i = 0; do{ - if (i != 0){Util::wait(1000);} + if (i != 0){Util::wait(Util::expBackoffMs(i-1, 10, 10000));} handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name.c_str()); i++; - }while (i < 10 && !handle && autoBackoff); + }while (i <= 10 && !handle && autoBackoff); } if (!handle){ MEDIUM_MSG("%s for page %s failed with error code %u", @@ -489,9 +489,9 @@ namespace IPC{ handle = shm_open(name.c_str(), O_CREAT | O_RDWR, ACCESSPERMS); }else{ int i = 0; - while (i < 10 && handle == -1 && autoBackoff){ + while (i < 11 && handle == -1 && autoBackoff){ i++; - Util::wait(1000); + Util::wait(Util::expBackoffMs(i-1, 10, 10000)); handle = shm_open(name.c_str(), O_RDWR, ACCESSPERMS); } } @@ -620,9 +620,9 @@ namespace IPC{ O_CREAT | O_TRUNC | O_RDWR, (mode_t)0600); }else{ int i = 0; - while (i < 10 && handle == -1 && autoBackoff){ + while (i < 11 && handle == -1 && autoBackoff){ i++; - Util::wait(1000); + Util::wait(Util::expBackoffMs(i-1, 10, 10000)); handle = open(std::string(Util::getTmpFolder() + name).c_str(), O_RDWR, (mode_t)0600); } } diff --git a/lib/util.cpp b/lib/util.cpp index bd324272..852a6f4d 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -149,6 +149,21 @@ namespace Util{ } } + //Returns the time to wait in milliseconds for exponential back-off waiting. + //If currIter > maxIter, always returns 5ms to prevent tight eternal loops when mistakes are made + //Otherwise, exponentially increases wait time for a total of maxWait milliseconds after maxIter calls. + //Wildly inaccurate for very short max durations and/or very large maxIter values, but otherwise works as expected. + int64_t expBackoffMs(const size_t currIter, const size_t maxIter, const int64_t maxWait){ + if (currIter > maxIter){return 5;} + int64_t w = maxWait >> 1; + for (size_t i = maxIter; i > currIter; --i){ + w >>= 1; + if (w < 2){w = 2;} + } + DONTEVEN_MSG("Waiting %" PRId64 " ms out of %" PRId64 " for iteration %zu/%zu", w, maxWait, currIter, maxIter); + return w; + } + /// 64-bits version of ftell uint64_t ftell(FILE *stream){ /// \TODO Windows implementation (e.g. _ftelli64 ?) diff --git a/lib/util.h b/lib/util.h index af77abf2..c19f32e1 100644 --- a/lib/util.h +++ b/lib/util.h @@ -14,6 +14,8 @@ namespace Util{ bool stringScan(const std::string &src, const std::string &pattern, std::deque &result); void stringToLower(std::string &val); + int64_t expBackoffMs(const size_t currIter, const size_t maxIter, const int64_t maxWait); + uint64_t ftell(FILE *stream); uint64_t fseek(FILE *stream, uint64_t offset, int whence);