[qwaq] Be a little paranoid about cond wait timeouts

I'd left qwaq-curses running overnight and found it locked up: both
threads were looping because pthread_cond_timedwait was returning
EINVAL. Thus bail if anything other than 0 is returned, and try to
ensure tv_nsec is in the range 0..999999999
This commit is contained in:
Bill Currie 2020-03-22 08:35:37 +09:00
parent 243840daa7
commit 486728a4bd
2 changed files with 9 additions and 7 deletions

View file

@ -577,11 +577,11 @@ dump_command (qwaq_resources_t *res, int len)
void void
qwaq_init_timeout (struct timespec *timeout, long time) qwaq_init_timeout (struct timespec *timeout, long time)
{ {
#define SEC 1000000000 #define SEC 1000000000L
struct timeval now; struct timeval now;
gettimeofday(&now, 0); gettimeofday(&now, 0);
timeout->tv_sec = now.tv_sec; timeout->tv_sec = now.tv_sec;
timeout->tv_nsec = now.tv_usec * 1000 + time; timeout->tv_nsec = now.tv_usec * 1000L + time;
if (timeout->tv_nsec > SEC) { if (timeout->tv_nsec > SEC) {
timeout->tv_sec += timeout->tv_nsec / SEC; timeout->tv_sec += timeout->tv_nsec / SEC;
timeout->tv_nsec %= SEC; timeout->tv_nsec %= SEC;
@ -598,7 +598,7 @@ process_commands (qwaq_resources_t *res)
pthread_mutex_lock (&res->command_cond.mut); pthread_mutex_lock (&res->command_cond.mut);
qwaq_init_timeout (&timeout, 20 * 1000000); qwaq_init_timeout (&timeout, 20 * 1000000);
while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret != ETIMEDOUT) { while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret == 0) {
ret = pthread_cond_timedwait (&res->command_cond.rcond, ret = pthread_cond_timedwait (&res->command_cond.rcond,
&res->command_cond.mut, &timeout); &res->command_cond.mut, &timeout);
} }
@ -700,23 +700,25 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event)
{ {
struct timespec timeout; struct timespec timeout;
int ret = 0; int ret = 0;
int was_event = 0;
pthread_mutex_lock (&res->event_cond.mut); pthread_mutex_lock (&res->event_cond.mut);
qwaq_init_timeout (&timeout, 20 * 1000000); qwaq_init_timeout (&timeout, 20 * 1000000);
while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret == 0) {
ret = pthread_cond_timedwait (&res->event_cond.rcond, ret = pthread_cond_timedwait (&res->event_cond.rcond,
&res->event_cond.mut, &timeout); &res->event_cond.mut, &timeout);
} }
if (event) { if (event) {
if (ret != ETIMEDOUT) { if (ret == 0) {
RB_READ_DATA (res->event_queue, event, 1); RB_READ_DATA (res->event_queue, event, 1);
was_event = 1;
} else { } else {
event->what = qe_none; event->what = qe_none;
} }
} }
pthread_cond_broadcast (&res->event_cond.wcond); pthread_cond_broadcast (&res->event_cond.wcond);
pthread_mutex_unlock (&res->event_cond.mut); pthread_mutex_unlock (&res->event_cond.mut);
return ret != ETIMEDOUT; return was_event;
} }
static int need_endwin; static int need_endwin;

View file

@ -77,7 +77,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event)
pthread_mutex_lock (&res->event_cond.mut); pthread_mutex_lock (&res->event_cond.mut);
qwaq_init_timeout (&timeout, 5000 * 1000000L); qwaq_init_timeout (&timeout, 5000 * 1000000L);
while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret == 0) {
ret = pthread_cond_timedwait (&res->event_cond.wcond, ret = pthread_cond_timedwait (&res->event_cond.wcond,
&res->event_cond.mut, &timeout); &res->event_cond.mut, &timeout);
} }