diff --git a/src/lib/ioloop-private.h b/src/lib/ioloop-private.h index d134b3f91c..dd39ad82d1 100644 --- a/src/lib/ioloop-private.h +++ b/src/lib/ioloop-private.h @@ -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; diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index af708ec195..40bc2c4ad1 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -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) { @@ -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) diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index 7001327e94..acb8ad957b 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -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 *