Skip to content

Commit

Permalink
lib: Add io_set_never_wait_alone()
Browse files Browse the repository at this point in the history
If ioloop is run without any timeouts and without IOs that don't have this
flag, assert-crash rather than going to infinite wait.
  • Loading branch information
sirainen committed Aug 22, 2018
1 parent 673e0aa commit 639c760
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/lib/ioloop-private.h
Expand Up @@ -42,6 +42,9 @@ struct io {
/* trigger I/O callback even if OS doesn't think there is input
pending */
bool pending;
/* This IO event shouldn't be the only thing being waited on, because
it would just result in infinite wait. */
bool never_wait_alone;

io_callback_t *callback;
void *context;
Expand Down
21 changes: 20 additions & 1 deletion src/lib/ioloop.c
Expand Up @@ -215,6 +215,11 @@ void io_set_pending(struct io *io)
}
}

void io_set_never_wait_alone(struct io *io, bool set)
{
io->never_wait_alone = set;
}

static void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
{
if (tv_now == NULL) {
Expand Down Expand Up @@ -512,9 +517,23 @@ static int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r)
return msecs;
}

static bool io_loop_have_waitable_io_files(struct ioloop *ioloop)
{
struct io_file *io;

for (io = ioloop->io_files; io != NULL; io = io->next) {
if (io->io.callback != NULL && !io->io.never_wait_alone)
return TRUE;
}
return FALSE;
}

int io_loop_run_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r)
{
return io_loop_get_wait_time(ioloop, tv_r);
int msecs = io_loop_get_wait_time(ioloop, tv_r);
if (msecs < 0 && !io_loop_have_waitable_io_files(ioloop))
i_panic("BUG: No IOs or timeouts set. Not waiting for infinity.");
return msecs;
}

static int timeout_cmp(const void *p1, const void *p2)
Expand Down
4 changes: 4 additions & 0 deletions src/lib/ioloop.h
Expand Up @@ -104,6 +104,10 @@ void io_remove_closed(struct io **io);
if some of the input has already read into some internal buffer and the
caller wants to handle it the same way as if the fd itself had input. */
void io_set_pending(struct io *io);
/* If set, this IO shouldn't be the only thing being waited on, because
it would just result in infinite wait. In those situations rather just
crash to indicate that there's a bug. */
void io_set_never_wait_alone(struct io *io, bool set);

/* Timeout handlers */
struct timeout *
Expand Down

0 comments on commit 639c760

Please sign in to comment.