1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-11 17:51:04 +00:00

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 cb99ce0f99
commit 618ef90c77
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) // timeout is absolute (using cond_clockid)
// returns false on timeout // 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); pthread_mutex_lock(&buf->mutex);
while (!buf->posted) { while (!buf->posted) {
if (timeout) { if (timeout) {
if (pthread_cond_timedwait(&buf->cond, &buf->mutex, timeout) == ETIMEDOUT) auto err = pthread_cond_timedwait(&buf->cond, &buf->mutex, timeout);
return false; 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 { } else {
pthread_cond_wait(&buf->cond, &buf->mutex); pthread_cond_wait(&buf->cond, &buf->mutex);
} }
} }
buf->posted = false; buf->posted = false;
pthread_mutex_unlock(&buf->mutex); pthread_mutex_unlock(&buf->mutex);
return true; return !timed_out;
} }
static void post(IPCChannelBuffer *buf) noexcept static void post(IPCChannelBuffer *buf) noexcept
@ -172,6 +187,8 @@ static bool wait_in(IPCChannelEnd::Dir *dir, u64 timeout_ms_abs)
#else #else
struct timespec timeout; struct timespec timeout;
struct timespec *timeoutp = nullptr; struct timespec *timeoutp = nullptr;
char timestr[201];
timestr[0] = '\0';
if (timeout_ms_abs > 0) { if (timeout_ms_abs > 0) {
u64 tnow = porting::getTimeMs(); u64 tnow = porting::getTimeMs();
if (tnow > timeout_ms_abs) 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_sec = 0;
timeout.tv_nsec = 0; timeout.tv_nsec = 0;
#elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) #elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX)
// Absolute time, relative to cond_clockid // Absolute time
FATAL_ERROR_IF(clock_gettime(dir->buf_in->cond_clockid, &timeout) < 0, FATAL_ERROR_IF(clock_gettime(CLOCK_REALTIME, &timeout) < 0,
"clock_gettime failed"); "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) { if (timeout.tv_nsec >= 1000'000'000L) {
timeout.tv_nsec -= 1000'000'000L; timeout.tv_nsec -= 1000'000'000L;
timeout.tv_sec += 1; timeout.tv_sec += 1;
} }
#endif
timeout.tv_sec += timeout_ms_rel / 1000;
timeout.tv_nsec += timeout_ms_rel % 1000 * 1000'000L;
timeoutp = &timeout; 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 #endif
} }
@ -226,6 +248,7 @@ IPCChannelBuffer::IPCChannelBuffer()
#if defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) #if defined(IPC_CHANNEL_IMPLEMENTATION_POSIX)
pthread_condattr_t condattr; pthread_condattr_t condattr;
pthread_mutexattr_t mutexattr; pthread_mutexattr_t mutexattr;
clockid_t cond_clockid;
if (pthread_condattr_init(&condattr) != 0) if (pthread_condattr_init(&condattr) != 0)
goto error_condattr_init; goto error_condattr_init;
if (pthread_mutexattr_init(&mutexattr) != 0) if (pthread_mutexattr_init(&mutexattr) != 0)
@ -242,6 +265,12 @@ IPCChannelBuffer::IPCChannelBuffer()
goto error_mutex_init; goto error_mutex_init;
pthread_mutexattr_destroy(&mutexattr); pthread_mutexattr_destroy(&mutexattr);
pthread_condattr_destroy(&condattr); 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; return;
error_mutex_init: error_mutex_init:
@ -350,7 +379,7 @@ bool IPCChannelEnd::recvWithTimeout(int timeout_ms) noexcept
m_large_recv.resize(size); m_large_recv.resize(size);
} catch (...) { } catch (...) {
// it's ok for us if an attacker wants to make us abort // 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); + std::to_string(size);
FATAL_ERROR(errmsg.c_str()); 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) #if defined(_WIN32)
#define IPC_CHANNEL_IMPLEMENTATION_WIN32 #define IPC_CHANNEL_IMPLEMENTATION_WIN32
#elif defined(__linux__) #elif defined(__linux__) && 0
#define IPC_CHANNEL_IMPLEMENTATION_LINUX_FUTEX #define IPC_CHANNEL_IMPLEMENTATION_LINUX_FUTEX
#else #else
#define IPC_CHANNEL_IMPLEMENTATION_POSIX #define IPC_CHANNEL_IMPLEMENTATION_POSIX
@ -71,7 +71,6 @@ struct IPCChannelBuffer
#elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX) #elif defined(IPC_CHANNEL_IMPLEMENTATION_POSIX)
pthread_cond_t cond; pthread_cond_t cond;
clockid_t cond_clockid;
pthread_mutex_t mutex; pthread_mutex_t mutex;
bool posted = false; // protected by mutex bool posted = false; // protected by mutex
#endif #endif