From 618ef90c77f754540d6c0c596e14958b24e78498 Mon Sep 17 00:00:00 2001 From: Desour Date: Mon, 7 Oct 2024 16:33:43 +0200 Subject: [PATCH] fix build, CLOCK_REALTIME is default, and getclock is too new. and fix infinite loop with lock becuase of nsec too big it took me way too long long to figure both of these out. why are the man pages missing all the important details?! at least the new versions of the posix standard are helpful: https://pubs.opengroup.org/onlinepubs/9699919799/ --- src/threading/ipc_channel.cpp | 53 +++++++++++++++++++++++++++-------- src/threading/ipc_channel.h | 3 +- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/threading/ipc_channel.cpp b/src/threading/ipc_channel.cpp index 4b0f37a54..1cfd07412 100644 --- a/src/threading/ipc_channel.cpp +++ b/src/threading/ipc_channel.cpp @@ -128,20 +128,35 @@ static void post(IPCChannelBuffer *buf) noexcept // timeout is absolute (using cond_clockid) // returns false on timeout -static bool wait(IPCChannelBuffer *buf, const struct timespec *timeout) noexcept +static bool wait(IPCChannelBuffer *buf, const struct timespec *timeout, const char *timestr = nullptr) noexcept { + if (timestr) + errorstream << timestr << std::endl; + bool timed_out = false; pthread_mutex_lock(&buf->mutex); while (!buf->posted) { if (timeout) { - if (pthread_cond_timedwait(&buf->cond, &buf->mutex, timeout) == ETIMEDOUT) - return false; + auto err = pthread_cond_timedwait(&buf->cond, &buf->mutex, timeout); + if (err == ETIMEDOUT) { + timed_out = true; + break; + } else if (err == EINTR || err == EOWNERDEAD || err == ENOTRECOVERABLE || err == EPERM || err == EINVAL) { + continue; + } else if (err != 0) { + pthread_mutex_unlock(&buf->mutex); + auto msg = "err: " + std::to_string(err); + FATAL_ERROR(msg.c_str()); + bool ret = wait(buf, timeout, msg.c_str()); + errorstream << msg << std::endl; + return ret; + } } else { pthread_cond_wait(&buf->cond, &buf->mutex); } } buf->posted = false; pthread_mutex_unlock(&buf->mutex); - return true; + return !timed_out; } static void post(IPCChannelBuffer *buf) noexcept @@ -172,6 +187,8 @@ static bool wait_in(IPCChannelEnd::Dir *dir, u64 timeout_ms_abs) #else struct timespec timeout; struct timespec *timeoutp = nullptr; + char timestr[201]; + timestr[0] = '\0'; if (timeout_ms_abs > 0) { u64 tnow = porting::getTimeMs(); if (tnow > timeout_ms_abs) @@ -182,21 +199,26 @@ static bool wait_in(IPCChannelEnd::Dir *dir, u64 timeout_ms_abs) timeout.tv_sec = 0; timeout.tv_nsec = 0; #elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) - // Absolute time, relative to cond_clockid - FATAL_ERROR_IF(clock_gettime(dir->buf_in->cond_clockid, &timeout) < 0, + // Absolute time + FATAL_ERROR_IF(clock_gettime(CLOCK_REALTIME, &timeout) < 0, "clock_gettime failed"); - // prevent overflow +#endif + timeout.tv_sec += timeout_ms_rel / 1000; + timeout.tv_nsec += timeout_ms_rel % 1000 * 1000'000L; + // tv_nsec must be smaller than 1 sec, or else pthread_cond_timedwait fails if (timeout.tv_nsec >= 1000'000'000L) { timeout.tv_nsec -= 1000'000'000L; timeout.tv_sec += 1; } -#endif - timeout.tv_sec += timeout_ms_rel / 1000; - timeout.tv_nsec += timeout_ms_rel % 1000 * 1000'000L; timeoutp = &timeout; + + time_t timeout_tt = timeout.tv_sec + timeout.tv_nsec / 1000'000'000L; + tm timeout_tm; + localtime_r(&timeout_tt, &timeout_tm); + strftime(timestr, 200, "%F %T ", &timeout_tm); } - return wait(dir->buf_in, timeoutp); + return wait(dir->buf_in, timeoutp, timestr); #endif } @@ -226,6 +248,7 @@ IPCChannelBuffer::IPCChannelBuffer() #if defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) pthread_condattr_t condattr; pthread_mutexattr_t mutexattr; + clockid_t cond_clockid; if (pthread_condattr_init(&condattr) != 0) goto error_condattr_init; if (pthread_mutexattr_init(&mutexattr) != 0) @@ -242,6 +265,12 @@ IPCChannelBuffer::IPCChannelBuffer() goto error_mutex_init; pthread_mutexattr_destroy(&mutexattr); pthread_condattr_destroy(&condattr); +/* + { + std::string bla = std::string("realt: ") + std::to_string(CLOCK_REALTIME) + " cond_clockid: " + std::to_string(cond_clockid); + FATAL_ERROR(bla.c_str()); + }*/ + FATAL_ERROR_IF(cond_clockid != CLOCK_REALTIME, "wrong clock"); return; error_mutex_init: @@ -350,7 +379,7 @@ bool IPCChannelEnd::recvWithTimeout(int timeout_ms) noexcept m_large_recv.resize(size); } catch (...) { // it's ok for us if an attacker wants to make us abort - std::string errmsg = std::string("std::vector::resize failed, size was: ") + std::string errmsg = "std::vector::resize failed, size was: " + std::to_string(size); FATAL_ERROR(errmsg.c_str()); } diff --git a/src/threading/ipc_channel.h b/src/threading/ipc_channel.h index 09acd09ec..eafc2c2a6 100644 --- a/src/threading/ipc_channel.h +++ b/src/threading/ipc_channel.h @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #if defined(_WIN32) #define IPC_CHANNEL_IMPLEMENTATION_WIN32 -#elif defined(__linux__) +#elif defined(__linux__) && 0 #define IPC_CHANNEL_IMPLEMENTATION_LINUX_FUTEX #else #define IPC_CHANNEL_IMPLEMENTATION_POSIX @@ -71,7 +71,6 @@ struct IPCChannelBuffer #elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) pthread_cond_t cond; - clockid_t cond_clockid; pthread_mutex_t mutex; bool posted = false; // protected by mutex #endif