changeset 3613:c4c1b538d8d0 HEAD

Added IO_ERROR condition that we can watch now.
author Timo Sirainen <tss@iki.fi>
date Sun, 25 Sep 2005 13:19:51 +0300
parents c64473977187
children 67703a43b23f
files src/lib/ioloop-epoll.c src/lib/ioloop-poll.c src/lib/ioloop-select.c src/lib/ioloop.h
diffstat 4 files changed, 68 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/ioloop-epoll.c	Sat Sep 24 19:32:54 2005 +0300
+++ b/src/lib/ioloop-epoll.c	Sun Sep 25 13:19:51 2005 +0300
@@ -26,6 +26,7 @@
 enum {
 	EPOLL_LIST_INPUT,
 	EPOLL_LIST_OUTPUT,
+	EPOLL_LIST_ERROR,
 
 	EPOLL_IOS_PER_FD
 };
@@ -76,8 +77,9 @@
 	p_free(ioloop->pool, ioloop->handler_context);
 }
 
-#define IO_EPOLL_INPUT	(EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP)
-#define IO_EPOLL_OUTPUT	(EPOLLOUT | EPOLLERR | EPOLLHUP)
+#define IO_EPOLL_ERROR (EPOLLERR | EPOLLHUP)
+#define IO_EPOLL_INPUT (EPOLLIN | EPOLLPRI | IO_EPOLL_ERROR)
+#define IO_EPOLL_OUTPUT	(EPOLLOUT | IO_EPOLL_ERROR)
 
 static int epoll_event_mask(struct io_list *list)
 {
@@ -94,6 +96,8 @@
 			events |= IO_EPOLL_INPUT;
 		if (io->condition & IO_WRITE)
 			events |= IO_EPOLL_OUTPUT;
+		if (io->condition & IO_ERROR)
+			events |= IO_EPOLL_ERROR;
 	}
 
 	return events;
@@ -101,34 +105,43 @@
 
 static int iolist_add(struct io_list *list, struct io *io)
 {
-	if ((io->condition & IO_READ) != 0) {
-		i_assert(list->ios[EPOLL_LIST_INPUT] == NULL);
-		list->ios[EPOLL_LIST_INPUT] = io;
-		return list->ios[EPOLL_LIST_OUTPUT] == NULL;
-	}
-	if ((io->condition & IO_WRITE) != 0) {
-		i_assert(list->ios[EPOLL_LIST_OUTPUT] == NULL);
-		list->ios[EPOLL_LIST_OUTPUT] = io;
-		return list->ios[EPOLL_LIST_INPUT] == NULL;
+	int i, idx;
+
+	if ((io->condition & IO_READ) != 0)
+		idx = EPOLL_LIST_INPUT;
+	else if ((io->condition & IO_WRITE) != 0)
+		idx = EPOLL_LIST_OUTPUT;
+	else if ((io->condition & IO_ERROR) != 0)
+		idx = EPOLL_LIST_ERROR;
+	else {
+		i_unreached();
 	}
 
-	i_unreached();
+	i_assert(list->ios[idx] == NULL);
+	list->ios[idx] = io;
+
+	/* check if this was the first one */
+	for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
+		if (i != idx && list->ios[i] != NULL)
+			return FALSE;
+	}
+
 	return TRUE;
 }
 
 static int iolist_del(struct io_list *list, struct io *io)
 {
-	if (list->ios[EPOLL_LIST_INPUT] == io) {
-		list->ios[EPOLL_LIST_INPUT] = NULL;
-		return list->ios[EPOLL_LIST_OUTPUT] == NULL;
+	int i, last = TRUE;
+
+	for (i = 0; i < EPOLL_IOS_PER_FD; i++) {
+		if (list->ios[i] != NULL) {
+			if (list->ios[i] == io)
+				list->ios[i] = NULL;
+			else
+				last = TRUE;
+		}
 	}
-	if (list->ios[EPOLL_LIST_OUTPUT] == io) {
-		list->ios[EPOLL_LIST_OUTPUT] = NULL;
-		return list->ios[EPOLL_LIST_INPUT] == NULL;
-	}
-
-	i_unreached();
-	return TRUE;
+	return last;
 }
 
 void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
@@ -221,13 +234,14 @@
 				continue;
 
 			call = FALSE;
-			if ((event->events & (EPOLLHUP | EPOLLERR)) != 0) {
+			if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
 				call = TRUE;
-			} else if ((io->condition & IO_READ) != 0) {
-				call = event->events & EPOLLIN;
-			} else if ((io->condition & IO_WRITE) != 0) {
-				call = event->events & EPOLLOUT;
-			}
+			else if ((io->condition & IO_READ) != 0)
+				call = (event->events & EPOLLIN) != 0;
+			else if ((io->condition & IO_WRITE) != 0)
+				call = (event->events & EPOLLOUT) != 0;
+			else if ((io->condition & IO_ERROR) != 0)
+				call = (event->events & IO_EPOLL_ERROR) != 0;
 
 			if (call) {
 				t_id = t_push();
--- a/src/lib/ioloop-poll.c	Sat Sep 24 19:32:54 2005 +0300
+++ b/src/lib/ioloop-poll.c	Sun Sep 25 13:19:51 2005 +0300
@@ -42,8 +42,9 @@
         p_free(ioloop->pool, ioloop->handler_context);
 }
 
-#define IO_POLL_INPUT (POLLIN|POLLPRI|POLLERR|POLLHUP|POLLNVAL)
-#define IO_POLL_OUTPUT (POLLOUT|POLLERR|POLLHUP|POLLNVAL)
+#define IO_POLL_ERROR (POLLERR|POLLHUP|POLLNVAL)
+#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 *io)
 {
@@ -95,6 +96,8 @@
 		ctx->fds[index].events |= IO_POLL_INPUT;
         if (condition & IO_WRITE)
 		ctx->fds[index].events |= IO_POLL_OUTPUT;
+	if (condition & IO_ERROR)
+		ctx->fds[index].events |= IO_POLL_ERROR;
 }
 
 void io_loop_handle_remove(struct ioloop *ioloop,  struct io *io)
@@ -172,6 +175,9 @@
 			} else if (io->condition & IO_WRITE) {
 				call = (pollfd->revents & IO_POLL_OUTPUT) != 0;
 				pollfd->revents &= ~IO_POLL_OUTPUT;
+			} else if (io->condition & IO_ERROR) {
+				call = (pollfd->revents & IO_POLL_ERROR) != 0;
+				pollfd->revents &= ~IO_POLL_ERROR;
 			} else {
 				call = FALSE;
 			}
--- a/src/lib/ioloop-select.c	Sat Sep 24 19:32:54 2005 +0300
+++ b/src/lib/ioloop-select.c	Sun Sep 25 13:19:51 2005 +0300
@@ -13,10 +13,10 @@
 
 struct ioloop_handler_context {
 	int highest_fd;
-	fd_set read_fds, write_fds;
+	fd_set read_fds, write_fds, except_fds;
 };
 
-static fd_set tmp_read_fds, tmp_write_fds;
+static fd_set tmp_read_fds, tmp_write_fds, tmp_except_fds;
 
 static void update_highest_fd(struct ioloop *ioloop)
 {
@@ -44,6 +44,7 @@
 	ioloop->handler_context->highest_fd = -1;
         FD_ZERO(&ioloop->handler_context->read_fds);
 	FD_ZERO(&ioloop->handler_context->write_fds);
+	FD_ZERO(&ioloop->handler_context->except_fds);
 }
 
 void io_loop_handler_deinit(struct ioloop *ioloop)
@@ -65,6 +66,7 @@
 		FD_SET(fd, &ioloop->handler_context->read_fds);
         if (condition & IO_WRITE)
 		FD_SET(fd, &ioloop->handler_context->write_fds);
+	FD_SET(fd, &ioloop->handler_context->except_fds);
 
 	if (io->fd > ioloop->handler_context->highest_fd)
 		ioloop->handler_context->highest_fd = io->fd;
@@ -82,14 +84,20 @@
         if (condition & IO_WRITE)
 		FD_CLR(fd, &ioloop->handler_context->write_fds);
 
-	/* check if we removed the highest fd */
-	if (io->fd == ioloop->handler_context->highest_fd)
-		update_highest_fd(ioloop);
+	if (!FD_ISSET(fd, &ioloop->handler_context->read_fds) &&
+	    !FD_ISSET(fd, &ioloop->handler_context->write_fds)) {
+		FD_CLR(fd, &ioloop->handler_context->except_fds);
+
+		/* check if we removed the highest fd */
+		if (io->fd == ioloop->handler_context->highest_fd)
+			update_highest_fd(ioloop);
+	}
 }
 
 #define io_check_condition(fd, condition) \
 	((FD_ISSET((fd), &tmp_read_fds) && ((condition) & IO_READ)) || \
-	 (FD_ISSET((fd), &tmp_write_fds) && ((condition) & IO_WRITE)))
+	 (FD_ISSET((fd), &tmp_write_fds) && ((condition) & IO_WRITE)) || \
+	 (FD_ISSET((fd), &tmp_except_fds)))
 
 void io_loop_handler_run(struct ioloop *ioloop)
 {
@@ -105,9 +113,11 @@
 	       sizeof(fd_set));
 	memcpy(&tmp_write_fds, &ioloop->handler_context->write_fds,
 	       sizeof(fd_set));
+	memcpy(&tmp_except_fds, &ioloop->handler_data->except_fds,
+	       sizeof(fd_set));
 
 	ret = select(ioloop->handler_context->highest_fd + 1,
-		     &tmp_read_fds, &tmp_write_fds, NULL, &tv);
+		     &tmp_read_fds, &tmp_write_fds, &tmp_except_fds, &tv);
 	if (ret < 0 && errno != EINTR)
 		i_warning("select() : %m");
 
--- a/src/lib/ioloop.h	Sat Sep 24 19:32:54 2005 +0300
+++ b/src/lib/ioloop.h	Sun Sep 25 13:19:51 2005 +0300
@@ -11,6 +11,7 @@
 enum io_condition {
 	IO_READ		= 0x01,
 	IO_WRITE	= 0x02,
+	IO_ERROR	= 0x04,
 	
 	/* internal */
 	IO_NOTIFY	= 0x04,