handle read from timerfd correctly

When reading the timerfd gives an error, we should return right away
because the timeout did not happen.

If we change the timerfd timeout before reading it, we can get -EAGAIN.
Don't log an error in that case but wait for the new timeout.
This commit is contained in:
Wim Taymans 2022-12-09 17:30:31 +01:00
parent 3a443b4e1c
commit f44d55f6c2
14 changed files with 153 additions and 55 deletions

View file

@ -839,11 +839,15 @@ static void media_on_flush_timeout(struct spa_source *source)
{
struct impl *this = source->data;
uint64_t exp;
int res;
spa_log_trace(this->log, "%p: flush on timeout", this);
if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
return;
}
if (this->transport == NULL) {
enable_flush_timer(this, false);
@ -864,12 +868,19 @@ static void media_on_timeout(struct spa_source *source)
uint32_t rate;
struct spa_io_buffers *io = port->io;
uint64_t prev_time, now_time;
int res;
if (this->transport == NULL)
return;
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if (this->started) {
if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s",
spa_strerror(res));
return;
}
}
prev_time = this->current_time;
now_time = this->current_time = this->next_time;

View file

@ -538,9 +538,13 @@ static void media_on_duplex_timeout(struct spa_source *source)
{
struct impl *this = source->data;
uint64_t exp;
int res;
if (spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if ((res = spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
return;
}
set_duplex_timeout(this, this->duplex_timeout);
@ -577,12 +581,18 @@ static void media_on_timeout(struct spa_source *source)
uint64_t exp, duration;
uint32_t rate;
uint64_t prev_time, now_time;
int res;
if (this->transport == NULL)
return;
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if (this->started) {
if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
return;
}
}
prev_time = this->current_time;
now_time = this->current_time = this->next_time;

View file

@ -567,16 +567,19 @@ stop:
enable_flush_timer(this, false);
}
static void sco_on_flush_timeout(struct spa_source *source)
{
struct impl *this = source->data;
uint64_t exp;
int res;
spa_log_trace(this->log, "%p: flush on timeout", this);
if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
return;
}
if (this->transport == NULL) {
enable_flush_timer(this, false);
@ -597,12 +600,18 @@ static void sco_on_timeout(struct spa_source *source)
uint32_t rate;
struct spa_io_buffers *io = port->io;
uint64_t prev_time, now_time;
int res;
if (this->transport == NULL)
return;
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if (this->started) {
if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
return;
}
}
prev_time = this->current_time;
now_time = this->current_time = this->next_time;

View file

@ -34,6 +34,7 @@
#include <spa/support/loop.h>
#include <spa/support/log.h>
#include <spa/support/system.h>
#include <spa/utils/result.h>
#include <spa/utils/list.h>
#include <spa/utils/keys.h>
#include <spa/utils/names.h>
@ -600,12 +601,19 @@ static void sco_on_timeout(struct spa_source *source)
uint64_t exp, duration;
uint32_t rate;
uint64_t prev_time, now_time;
int res;
if (this->transport == NULL)
return;
if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
if (this->started) {
if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
if (res != -EAGAIN)
spa_log_warn(this->log, "error reading timerfd: %s",
spa_strerror(res));
return;
}
}
prev_time = this->current_time;
now_time = this->current_time = this->next_time;