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:
parent
29fff36dfc
commit
5f577e674e
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user