From: Timo Sirainen Date: Sat, 1 Nov 2008 12:14:42 +0000 (+0200) Subject: Don't break if io_remove() or timeout_remove() are called for non-active ioloops. X-Git-Tag: 1.2.alpha4~123 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=193f5296d2a6b847970c222d8a261b89aae46331;p=thirdparty%2Fdovecot%2Fcore.git Don't break if io_remove() or timeout_remove() are called for non-active ioloops. --HG-- branch : HEAD --- diff --git a/src/lib/ioloop-epoll.c b/src/lib/ioloop-epoll.c index 9f7377e026..f657f57fad 100644 --- a/src/lib/ioloop-epoll.c +++ b/src/lib/ioloop-epoll.c @@ -83,9 +83,9 @@ static int epoll_event_mask(struct io_list *list) return events; } -void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) +void io_loop_handle_add(struct io_file *io) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; struct io_list **list; struct epoll_event event; int op; @@ -118,10 +118,9 @@ void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) } } -void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, - bool closed) +void io_loop_handle_remove(struct io_file *io, bool closed) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; struct io_list **list; struct epoll_event event; int op; diff --git a/src/lib/ioloop-internal.h b/src/lib/ioloop-internal.h index c153b1c01d..7a61be8270 100644 --- a/src/lib/ioloop-internal.h +++ b/src/lib/ioloop-internal.h @@ -26,6 +26,8 @@ struct io { io_callback_t *callback; void *context; + + struct ioloop *ioloop; }; struct io_file { @@ -46,6 +48,8 @@ struct timeout { timeout_callback_t *callback; void *context; + + struct ioloop *ioloop; }; int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r, @@ -53,14 +57,13 @@ int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r, void io_loop_handle_timeouts(struct ioloop *ioloop); /* I/O handler calls */ -void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io); -void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, - bool closed); +void io_loop_handle_add(struct io_file *io); +void io_loop_handle_remove(struct io_file *io, bool closed); void io_loop_handler_init(struct ioloop *ioloop); void io_loop_handler_deinit(struct ioloop *ioloop); -void io_loop_notify_remove(struct ioloop *ioloop, struct io *io); +void io_loop_notify_remove(struct io *io); void io_loop_notify_handler_deinit(struct ioloop *ioloop); #endif diff --git a/src/lib/ioloop-kqueue.c b/src/lib/ioloop-kqueue.c index c45e2870d5..e34792f466 100644 --- a/src/lib/ioloop-kqueue.c +++ b/src/lib/ioloop-kqueue.c @@ -56,9 +56,9 @@ void io_loop_handler_deinit(struct ioloop *ioloop) i_free(ioloop->handler_context); } -void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) +void io_loop_handle_add(struct io_file *io) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; struct kevent ev; if ((io->io.condition & (IO_READ | IO_ERROR)) != 0) { @@ -80,10 +80,9 @@ void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) (void)array_append_space(&ctx->events); } -void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, - bool closed) +void io_loop_handle_remove(struct io_file *io, bool closed) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; struct kevent ev; if ((io->io.condition & (IO_READ | IO_ERROR)) != 0 && !closed) { diff --git a/src/lib/ioloop-notify-dn.c b/src/lib/ioloop-notify-dn.c index 9466e778fe..c2a269ab2f 100644 --- a/src/lib/ioloop-notify-dn.c +++ b/src/lib/ioloop-notify-dn.c @@ -148,10 +148,10 @@ enum io_notify_result io_add_notify(const char *path, io_callback_t *callback, return IO_NOTIFY_ADDED; } -void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io) +void io_loop_notify_remove(struct io *_io) { struct ioloop_notify_handler_context *ctx = - ioloop->notify_handler_context; + _io->ioloop->notify_handler_context; struct io_notify *io = (struct io_notify *)_io; if (fcntl(io->fd, F_NOTIFY, 0) < 0) diff --git a/src/lib/ioloop-notify-fd.c b/src/lib/ioloop-notify-fd.c index 8dfcf378f4..5a8705f748 100644 --- a/src/lib/ioloop-notify-fd.c +++ b/src/lib/ioloop-notify-fd.c @@ -15,6 +15,7 @@ struct io *io_notify_fd_add(struct ioloop_notify_fd_context *ctx, int fd, io->io.condition = IO_NOTIFY; io->io.callback = callback; io->io.context = context; + io->io.ioloop = current_ioloop; io->fd = fd; if (ctx->notifies != NULL) { diff --git a/src/lib/ioloop-notify-inotify.c b/src/lib/ioloop-notify-inotify.c index d0a91ca2e6..6026feb2c6 100644 --- a/src/lib/ioloop-notify-inotify.c +++ b/src/lib/ioloop-notify-inotify.c @@ -120,10 +120,10 @@ enum io_notify_result io_add_notify(const char *path, io_callback_t *callback, return IO_NOTIFY_ADDED; } -void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io) +void io_loop_notify_remove(struct io *_io) { struct ioloop_notify_handler_context *ctx = - ioloop->notify_handler_context; + _io->ioloop->notify_handler_context; struct io_notify *io = (struct io_notify *)_io; if (io->fd != -1) { diff --git a/src/lib/ioloop-notify-kqueue.c b/src/lib/ioloop-notify-kqueue.c index 0477bd56ed..9ae2a9ef07 100644 --- a/src/lib/ioloop-notify-kqueue.c +++ b/src/lib/ioloop-notify-kqueue.c @@ -130,6 +130,7 @@ enum io_notify_result io_add_notify(const char *path, io_callback_t *callback, io->io.condition = IO_NOTIFY; io->io.callback = callback; io->io.context = context; + io->io.ioloop = current_ioloop; io->refcount = 1; io->fd = fd; @@ -147,16 +148,16 @@ enum io_notify_result io_add_notify(const char *path, io_callback_t *callback, if (ctx->event_io == NULL) { ctx->event_io = io_add(ctx->kq, IO_READ, event_callback, - current_ioloop->notify_handler_context); + io->io.ioloop->notify_handler_context); } *io_r = &io->io; return IO_NOTIFY_ADDED; } -void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io) +void io_loop_notify_remove(struct io *_io) { struct ioloop_notify_handler_context *ctx = - ioloop->notify_handler_context; + _io->ioloop->notify_handler_context; struct io_notify *io = (struct io_notify *)_io; struct kevent ev; diff --git a/src/lib/ioloop-notify-none.c b/src/lib/ioloop-notify-none.c index 4cef6eaf45..7dcde9f307 100644 --- a/src/lib/ioloop-notify-none.c +++ b/src/lib/ioloop-notify-none.c @@ -15,8 +15,7 @@ io_add_notify(const char *path ATTR_UNUSED, return IO_NOTIFY_NOSUPPORT; } -void io_loop_notify_remove(struct ioloop *ioloop ATTR_UNUSED, - struct io *io ATTR_UNUSED) +void io_loop_notify_remove(struct io *io ATTR_UNUSED) { } diff --git a/src/lib/ioloop-poll.c b/src/lib/ioloop-poll.c index ba8adfaf15..fc425e52c1 100644 --- a/src/lib/ioloop-poll.c +++ b/src/lib/ioloop-poll.c @@ -42,9 +42,9 @@ void io_loop_handler_deinit(struct ioloop *ioloop) #define IO_POLL_INPUT (POLLIN | POLLPRI | IO_POLL_ERROR) #define IO_POLL_OUTPUT (POLLOUT | IO_POLL_ERROR) -void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) +void io_loop_handle_add(struct io_file *io) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; enum io_condition condition = io->io.condition; unsigned int old_count; int index, fd = io->fd; @@ -94,10 +94,9 @@ void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) ctx->fds[index].events |= IO_POLL_ERROR; } -void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, - bool closed ATTR_UNUSED) +void io_loop_handle_remove(struct io_file *io, bool closed ATTR_UNUSED) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; enum io_condition condition = io->io.condition; int index, fd = io->fd; diff --git a/src/lib/ioloop-select.c b/src/lib/ioloop-select.c index 1c63637088..0a39652664 100644 --- a/src/lib/ioloop-select.c +++ b/src/lib/ioloop-select.c @@ -53,9 +53,9 @@ void io_loop_handler_deinit(struct ioloop *ioloop) i_free(ioloop->handler_context); } -void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) +void io_loop_handle_add(struct io_file *io) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; enum io_condition condition = io->io.condition; int fd = io->fd; @@ -74,10 +74,9 @@ void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io) ctx->highest_fd = io->fd; } -void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, - bool closed ATTR_UNUSED) +void io_loop_handle_remove(struct io_file *io, bool closed ATTR_UNUSED) { - struct ioloop_handler_context *ctx = ioloop->handler_context; + struct ioloop_handler_context *ctx = io->io.ioloop->handler_context; enum io_condition condition = io->io.condition; int fd = io->fd; @@ -93,7 +92,7 @@ void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io, /* check if we removed the highest fd */ if (io->fd == ctx->highest_fd) - update_highest_fd(ioloop); + update_highest_fd(io->io.ioloop); } i_free(io); } diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index 0d194d9a1f..deae0ce715 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -33,18 +33,19 @@ struct io *io_add(int fd, enum io_condition condition, io->io.condition = condition; io->io.callback = callback; io->io.context = context; + io->io.ioloop = current_ioloop; io->refcount = 1; io->fd = fd; - if (current_ioloop->handler_context == NULL) - io_loop_handler_init(current_ioloop); - io_loop_handle_add(current_ioloop, io); + if (io->io.ioloop->handler_context == NULL) + io_loop_handler_init(io->io.ioloop); + io_loop_handle_add(io); - if (current_ioloop->io_files != NULL) { - current_ioloop->io_files->prev = io; - io->next = current_ioloop->io_files; + if (io->io.ioloop->io_files != NULL) { + io->io.ioloop->io_files->prev = io; + io->next = io->io.ioloop->io_files; } - current_ioloop->io_files = io; + io->io.ioloop->io_files = io; return &io->io; } @@ -53,15 +54,15 @@ static void io_file_unlink(struct io_file *io) if (io->prev != NULL) io->prev->next = io->next; else - current_ioloop->io_files = io->next; + io->io.ioloop->io_files = io->next; if (io->next != NULL) io->next->prev = io->prev; /* if we got here from an I/O handler callback, make sure we don't try to handle this one next. */ - if (current_ioloop->next_io_file == io) - current_ioloop->next_io_file = io->next; + if (io->io.ioloop->next_io_file == io) + io->io.ioloop->next_io_file = io->next; } static void io_remove_full(struct io **_io, bool closed) @@ -77,12 +78,12 @@ static void io_remove_full(struct io **_io, bool closed) io->callback = NULL; if ((io->condition & IO_NOTIFY) != 0) - io_loop_notify_remove(current_ioloop, io); + io_loop_notify_remove(io); else { struct io_file *io_file = (struct io_file *)io; io_file_unlink(io_file); - io_loop_handle_remove(current_ioloop, io_file, closed); + io_loop_handle_remove(io_file, closed); } } @@ -129,13 +130,14 @@ struct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback, timeout = i_new(struct timeout, 1); timeout->msecs = msecs; + timeout->ioloop = current_ioloop; timeout->callback = callback; timeout->context = context; - timeout_update_next(timeout, current_ioloop->running ? + timeout_update_next(timeout, timeout->ioloop->running ? NULL : &ioloop_timeval); - priorityq_add(current_ioloop->timeouts, &timeout->item); + priorityq_add(timeout->ioloop->timeouts, &timeout->item); return timeout; } @@ -144,7 +146,7 @@ void timeout_remove(struct timeout **_timeout) struct timeout *timeout = *_timeout; *_timeout = NULL; - priorityq_remove(current_ioloop->timeouts, &timeout->item); + priorityq_remove(timeout->ioloop->timeouts, &timeout->item); i_free(timeout); } @@ -166,13 +168,13 @@ timeout_reset_timeval(struct timeout *timeout, struct timeval *tv_now) timeout->next_run.tv_sec > tv_now->tv_sec || (timeout->next_run.tv_sec == tv_now->tv_sec && timeout->next_run.tv_usec > tv_now->tv_usec)); - priorityq_remove(current_ioloop->timeouts, &timeout->item); - priorityq_add(current_ioloop->timeouts, &timeout->item); + priorityq_remove(timeout->ioloop->timeouts, &timeout->item); + priorityq_add(timeout->ioloop->timeouts, &timeout->item); } void timeout_reset(struct timeout *timeout) { - timeout_reset_timeval(timeout, current_ioloop->running ? NULL : + timeout_reset_timeval(timeout, timeout->ioloop->running ? NULL : &ioloop_timeval); } @@ -382,9 +384,14 @@ void io_loop_destroy(struct ioloop **_ioloop) if (ioloop->handler_context != NULL) io_loop_handler_deinit(ioloop); - /* ->prev won't work unless loops are destroyed in create order */ + /* ->prev won't work unless loops are destroyed in create order */ i_assert(ioloop == current_ioloop); current_ioloop = current_ioloop->prev; i_free(ioloop); } + +void io_loop_set_current(struct ioloop *ioloop) +{ + current_ioloop = ioloop; +} diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index f86b00dbd6..9d1c5ed852 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -91,4 +91,7 @@ struct ioloop *io_loop_create(void); /* Destroy I/O loop and set ioloop pointer to NULL. */ void io_loop_destroy(struct ioloop **ioloop); +/* Change the current_ioloop. */ +void io_loop_set_current(struct ioloop *ioloop); + #endif