dovecot-1.1: Added io_remove_closed().

dovecot at dovecot.org dovecot at dovecot.org
Thu Aug 21 07:36:49 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/0930aa699486
changeset: 7824:0930aa699486
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Aug 21 07:35:59 2008 +0300
description:
Added io_remove_closed().

diffstat:

7 files changed, 54 insertions(+), 30 deletions(-)
src/lib/ioloop-epoll.c    |   26 ++++++++++++++------------
src/lib/ioloop-internal.h |    3 ++-
src/lib/ioloop-kqueue.c   |    7 ++++---
src/lib/ioloop-poll.c     |   24 ++++++++++++++----------
src/lib/ioloop-select.c   |    3 ++-
src/lib/ioloop.c          |   18 +++++++++++++++---
src/lib/ioloop.h          |    3 +++

diffs (183 lines):

diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop-epoll.c
--- a/src/lib/ioloop-epoll.c	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop-epoll.c	Thu Aug 21 07:35:59 2008 +0300
@@ -118,7 +118,8 @@ void io_loop_handle_add(struct ioloop *i
 	}
 }
 
-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
 	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);
-
-	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 (!closed) {
+		memset(&event, 0, sizeof(event));
+		event.data.ptr = *list;
+		event.events = epoll_event_mask(*list);
+
+		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 (last) {
 		/* since we're not freeing memory in any case, just increase
 		   deleted counter so next handle_add() can just decrease it
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop-internal.h
--- a/src/lib/ioloop-internal.h	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop-internal.h	Thu Aug 21 07:35:59 2008 +0300
@@ -54,7 +54,8 @@ void io_loop_handle_timeouts(struct iolo
 
 /* 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);
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop-kqueue.c
--- a/src/lib/ioloop-kqueue.c	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop-kqueue.c	Thu Aug 21 07:35:59 2008 +0300
@@ -80,17 +80,18 @@ void io_loop_handle_add(struct ioloop *i
 		(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);
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop-poll.c
--- a/src/lib/ioloop-poll.c	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop-poll.c	Thu Aug 21 07:35:59 2008 +0300
@@ -94,7 +94,8 @@ void io_loop_handle_add(struct ioloop *i
 		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
 	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);
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop-select.c
--- a/src/lib/ioloop-select.c	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop-select.c	Thu Aug 21 07:35:59 2008 +0300
@@ -74,7 +74,8 @@ void io_loop_handle_add(struct ioloop *i
 		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;
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop.c
--- a/src/lib/ioloop.c	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop.c	Thu Aug 21 07:35:59 2008 +0300
@@ -64,7 +64,7 @@ static void io_file_unlink(struct io_fil
 		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,8 +82,20 @@ 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)
diff -r 7f5cc9e805ec -r 0930aa699486 src/lib/ioloop.h
--- a/src/lib/ioloop.h	Thu Aug 21 07:14:50 2008 +0300
+++ b/src/lib/ioloop.h	Thu Aug 21 07:35:59 2008 +0300
@@ -63,6 +63,9 @@ enum io_notify_result io_add_notify(cons
 
 /* 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,


More information about the dovecot-cvs mailing list