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/
This commit is contained in:
Desour 2024-10-07 16:33:43 +02:00
parent 29fff36dfc
commit 5f577e674e
2 changed files with 42 additions and 14 deletions

View File

@ -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());
}

View File

@ -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