]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added io_remove_closed().
authorTimo Sirainen <tss@iki.fi>
Thu, 21 Aug 2008 04:35:59 +0000 (07:35 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 21 Aug 2008 04:35:59 +0000 (07:35 +0300)
--HG--
branch : HEAD

src/lib/ioloop-epoll.c
src/lib/ioloop-internal.h
src/lib/ioloop-kqueue.c
src/lib/ioloop-poll.c
src/lib/ioloop-select.c
src/lib/ioloop.c
src/lib/ioloop.h

index 114b6b2b4cffd5faf186e0e00a179a5867bde96c..9f7377e0268e60a7d9c9cd4ff9a4bdadfe3e98f8 100644 (file)
@@ -118,7 +118,8 @@ void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
        }
 }
 
-void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io,
+                          bool closed)
 {
        struct ioloop_handler_context *ctx = ioloop->handler_context;
        struct io_list **list;
@@ -129,17 +130,18 @@ void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
        list = array_idx_modifiable(&ctx->fd_index, io->fd);
        last = ioloop_iolist_del(*list, io);
 
-       memset(&event, 0, sizeof(event));
-       event.data.ptr = *list;
-       event.events = epoll_event_mask(*list);
+       if (!closed) {
+               memset(&event, 0, sizeof(event));
+               event.data.ptr = *list;
+               event.events = epoll_event_mask(*list);
 
-       op = last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
+               op = last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
 
-       if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
-               i_error("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
-                       op, io->fd);
+               if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
+                       i_error("io_loop_handle_remove: epoll_ctl(%d, %d): %m",
+                               op, io->fd);
+               }
        }
-
        if (last) {
                /* since we're not freeing memory in any case, just increase
                   deleted counter so next handle_add() can just decrease it
index 80072c216745c5239a44255690a53d5df5d999a3..c153b1c01d6a49115a9bd0886205b8ece0448d18 100644 (file)
@@ -54,7 +54,8 @@ 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);
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io,
+                          bool closed);
 
 void io_loop_handler_init(struct ioloop *ioloop);
 void io_loop_handler_deinit(struct ioloop *ioloop);
index 286fdd206ebeba8125934b5572c9240c08cf5800..c45e2870d5d62a104b4b7646efd364bb1ca3f8b1 100644 (file)
@@ -80,17 +80,18 @@ 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)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io,
+                          bool closed)
 {
        struct ioloop_handler_context *ctx = ioloop->handler_context;
        struct kevent ev;
 
-       if ((io->io.condition & (IO_READ | IO_ERROR)) != 0) {
+       if ((io->io.condition & (IO_READ | IO_ERROR)) != 0 && !closed) {
                MY_EV_SET(&ev, io->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
                if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
                        i_error("kevent(EV_DELETE, %d) failed: %m", io->fd);
        }
-       if ((io->io.condition & IO_WRITE) != 0) {
+       if ((io->io.condition & IO_WRITE) != 0 && !closed) {
                MY_EV_SET(&ev, io->fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
                if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
                        i_error("kevent(EV_DELETE, %d) failed: %m", io->fd);
index 3d636e9d64dc2f4f525391463d97626738b59d0a..ba8adfaf15abb7481db3eb5b66bf8d543d54cfbb 100644 (file)
@@ -94,7 +94,8 @@ 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)
+void io_loop_handle_remove(struct ioloop *ioloop,  struct io_file *io,
+                          bool closed ATTR_UNUSED)
 {
        struct ioloop_handler_context *ctx = ioloop->handler_context;
        enum io_condition condition = io->io.condition;
@@ -104,15 +105,18 @@ void io_loop_handle_remove(struct ioloop *ioloop,  struct io_file *io)
        i_assert(index >= 0 && (unsigned int) index < ctx->fds_count);
 
 #ifdef DEBUG
-       /* io_remove() is required to be called before fd is closed.
-          This is required by kqueue, but since poll is more commonly used
-          while developing, this check here should catch the error early
-          enough not to cause problems for kqueue users. */
-       if (fcntl(io->fd, F_GETFD, 0) < 0) {
-               if (errno == EBADF)
-                       i_panic("io_remove(%d) called too late", io->fd);
-               else
-                       i_error("fcntl(%d, F_GETFD) failed: %m", io->fd);
+       if (!closed) {
+               /* io_remove() is required to be called before fd is closed.
+                  This is required by epoll/kqueue, but since poll is more
+                  commonly used while developing, this check here should catch
+                  the error early enough not to cause problems for kqueue
+                  users. */
+               if (fcntl(io->fd, F_GETFD, 0) < 0) {
+                       if (errno == EBADF)
+                               i_panic("io_remove(%d) called too late", io->fd);
+                       else
+                               i_error("fcntl(%d, F_GETFD) failed: %m", io->fd);
+               }
        }
 #endif
        i_free(io);
index 628b0f8b2cd23ce62c0ada72042602be6d8a9db0..1c636370884b0373e990af32bb05ef9fdb0ad056 100644 (file)
@@ -74,7 +74,8 @@ 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)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io,
+                          bool closed ATTR_UNUSED)
 {
        struct ioloop_handler_context *ctx = ioloop->handler_context;
        enum io_condition condition = io->io.condition;
index 406bebf1fa547f01f64df027c3e40992cc171081..0d194d9a1f426553f0ad53ce27b01b24f0d1ffdc 100644 (file)
@@ -64,7 +64,7 @@ static void io_file_unlink(struct io_file *io)
                current_ioloop->next_io_file = io->next;
 }
 
-void io_remove(struct io **_io)
+static void io_remove_full(struct io **_io, bool closed)
 {
        struct io *io = *_io;
 
@@ -82,10 +82,22 @@ void io_remove(struct io **_io)
                struct io_file *io_file = (struct io_file *)io;
 
                io_file_unlink(io_file);
-               io_loop_handle_remove(current_ioloop, io_file);
+               io_loop_handle_remove(current_ioloop, io_file, closed);
        }
 }
 
+void io_remove(struct io **io)
+{
+       io_remove_full(io, FALSE);
+}
+
+void io_remove_closed(struct io **io)
+{
+       i_assert(((*io)->condition & IO_NOTIFY) == 0);
+
+       io_remove_full(io, TRUE);
+}
+
 static void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
 {
        if (tv_now == NULL) {
index 67242c87f25e00099ce550f0a880bdd0e8136d12..f86b00dbd6129332d8d615e9e87f8a7bfe74f22e 100644 (file)
@@ -63,6 +63,9 @@ enum io_notify_result io_add_notify(const char *path, io_callback_t *callback,
 
 /* Remove I/O handler, and set io pointer to NULL. */
 void io_remove(struct io **io);
+/* Like io_remove(), but assume that the file descriptor is already closed.
+   With some backends this simply frees the memory. */
+void io_remove_closed(struct io **io);
 
 /* Timeout handlers */
 struct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback,