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

@ -215,15 +215,20 @@ static void set_timer(struct impl *this, bool enabled)
}
}
static inline void read_timer(struct impl *this)
static inline int read_timer(struct impl *this)
{
uint64_t expirations;
int res = 0;
if (this->callbacks.funcs || this->props.live) {
if (spa_system_timerfd_read(this->data_system,
this->timer_source.fd, &expirations) < 0)
perror("read timerfd");
if ((res = spa_system_timerfd_read(this->data_system,
this->timer_source.fd, &expirations)) < 0) {
if (res != -EAGAIN)
spa_log_error(this->log, NAME " %p: timerfd error: %s",
this, spa_strerror(res));
}
}
return res;
}
static void render_buffer(struct impl *this, struct buffer *b)
@ -237,7 +242,8 @@ static int consume_buffer(struct impl *this)
struct spa_io_buffers *io = port->io;
int n_bytes;
read_timer(this);
if (read_timer(this) < 0)
return 0;
if (spa_list_is_empty(&port->ready)) {
io->status = SPA_STATUS_NEED_DATA;

View file

@ -233,12 +233,17 @@ static void set_timer(struct impl *this, bool enabled)
static inline void read_timer(struct impl *this)
{
uint64_t expirations;
int res = 0;
if (this->callbacks.funcs || this->props.live) {
if (spa_system_timerfd_read(this->data_system,
this->timer_source.fd, &expirations) < 0)
perror("read timerfd");
if ((res = spa_system_timerfd_read(this->data_system,
this->timer_source.fd, &expirations)) < 0) {
if (res != -EAGAIN)
spa_log_error(this->log, NAME " %p: timerfd error: %s",
this, spa_strerror(res));
}
}
return res;
}
static int make_buffer(struct impl *this)
@ -248,7 +253,8 @@ static int make_buffer(struct impl *this)
struct spa_io_buffers *io = port->io;
int n_bytes;
read_timer(this);
if (read_timer(this) < 0)
return 0;
if (spa_list_is_empty(&port->empty)) {
set_timer(this, false);