From 66df8c72718174fa28af5f0ef16b02f6ee598feb Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 20 Dec 2007 16:37:57 -0600 Subject: [PATCH] Fix a lot of bad assumptions in the epoll code (this needs major testing). --- libcharybdis/epoll.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/libcharybdis/epoll.c b/libcharybdis/epoll.c index 5a30ef5..fd005b3 100644 --- a/libcharybdis/epoll.c +++ b/libcharybdis/epoll.c @@ -1,5 +1,5 @@ /* - * ircd-ratbox: A slightly useful ircd. + * charybdis: A slightly useful ircd. * epoll.c: Linux epoll compatible network routines. * * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center @@ -7,6 +7,7 @@ * Copyright (C) 2001 Adrian Chadd * Copyright (C) 2002-2005 ircd-ratbox development team * Copyright (C) 2002 Aaron Sethman + * Copyright (C) 2008 William Pitcock * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -133,8 +134,6 @@ comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, libcharybdis_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno)); abort(); } - - } /* @@ -178,7 +177,6 @@ comm_select(unsigned long delay) } else libcharybdis_log("epoll.c: NULL read handler called"); - } @@ -198,15 +196,30 @@ comm_select(unsigned long delay) libcharybdis_log("epoll.c: NULL write handler called"); } - if(F->flags.open == 0) - continue; + if(F->flags.open == 0 && F->pflags == 0) + continue; + else if (F->flags.open == 0) + { + F->pflags = ep_event.events = flags; + ep_event.data.ptr = F; + + if(epoll_ctl(ep, EPOLL_CTL_DEL, F->fd, &ep_event) != 0) { + libcharybdis_log("comm_select(): epoll_ctl failed while trying to delete a closed FD: %s", strerror(errno)); + abort(); + } + } flags = 0; if(F->read_handler != NULL) flags |= EPOLLIN; + else + flags &= ~EPOLLIN; + if(F->write_handler != NULL) flags |= EPOLLOUT; + else + flags &= ~EPOLLOUT; if(old_flags != flags) { @@ -214,12 +227,12 @@ comm_select(unsigned long delay) op = EPOLL_CTL_DEL; else op = EPOLL_CTL_MOD; + F->pflags = ep_event.events = flags; ep_event.data.ptr = F; + if(epoll_ctl(ep, op, F->fd, &ep_event) != 0) - { - libcharybdis_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno)); - } + libcharybdis_log("comm_select(): epoll_ctl failed: %s", strerror(errno)); } }