diff options
-rw-r--r-- | include/dns.h | 2 | ||||
-rw-r--r-- | include/inspircd.h | 2 | ||||
-rw-r--r-- | include/inspsocket.h | 2 | ||||
-rw-r--r-- | include/socket.h | 2 | ||||
-rw-r--r-- | include/socketengine.h | 8 | ||||
-rw-r--r-- | include/users.h | 2 | ||||
-rw-r--r-- | src/dns.cpp | 2 | ||||
-rw-r--r-- | src/inspircd.cpp | 2 | ||||
-rw-r--r-- | src/inspsocket.cpp | 4 | ||||
-rw-r--r-- | src/socket.cpp | 2 | ||||
-rw-r--r-- | src/socketengine_epoll.cpp | 21 | ||||
-rw-r--r-- | src/socketengine_select.cpp | 23 | ||||
-rw-r--r-- | src/users.cpp | 2 |
13 files changed, 51 insertions, 23 deletions
diff --git a/include/dns.h b/include/dns.h index b011a9ddb..79b286233 100644 --- a/include/dns.h +++ b/include/dns.h @@ -330,7 +330,7 @@ class DNS : public EventHandler * Handle a SocketEngine read event * Inherited from EventHandler */ - void HandleEvent(EventType et); + void HandleEvent(EventType et, int errornum = 0); /** * Add a Resolver* to the list of active classes diff --git a/include/inspircd.h b/include/inspircd.h index 3a752e21c..014f729b0 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -172,7 +172,7 @@ class FileLogger : public EventHandler * another write event is scheduled to write * the rest of the data when possible. */ - virtual void HandleEvent(EventType et); + virtual void HandleEvent(EventType et, int errornum = 0); /** Write one or more preformatted log lines. * If the data cannot be written immediately, * this class will insert itself into the diff --git a/include/inspsocket.h b/include/inspsocket.h index af92615ea..71f16951e 100644 --- a/include/inspsocket.h +++ b/include/inspsocket.h @@ -365,7 +365,7 @@ class InspSocket : public EventHandler */ void MarkAsClosed(); - void HandleEvent(EventType et); + void HandleEvent(EventType et, int errornum = 0); bool Readable(); }; diff --git a/include/socket.h b/include/socket.h index f868daf92..6264b196f 100644 --- a/include/socket.h +++ b/include/socket.h @@ -154,7 +154,7 @@ class ListenSocket : public EventHandler ListenSocket(InspIRCd* Instance, int sockfd, irc::sockets::insp_sockaddr client, irc::sockets::insp_sockaddr server, int port, char* addr); /** Handle an I/O event */ - void HandleEvent(EventType et); + void HandleEvent(EventType et, int errornum = 0); }; #endif diff --git a/include/socketengine.h b/include/socketengine.h index a4628b648..9b3cdec64 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -26,11 +26,15 @@ /** Types of event an EventHandler may receive. * EVENT_READ is a readable file descriptor, * and EVENT_WRITE is a writeable file descriptor. + * EVENT_ERROR can always occur, and indicates + * a write error or read error on the socket, + * e.g. EOF condition or broken pipe. */ enum EventType { EVENT_READ = 0, - EVENT_WRITE = 1 + EVENT_WRITE = 1, + EVENT_ERROR = 2 }; class InspIRCd; @@ -127,7 +131,7 @@ class EventHandler : public Extensible * @param et either one of EVENT_READ for read events, * and EVENT_WRITE for write events. */ - virtual void HandleEvent(EventType et) = 0; + virtual void HandleEvent(EventType et, int errornum = 0) = 0; }; /** Provides basic file-descriptor-based I/O support. diff --git a/include/users.h b/include/users.h index 1dc0aa43e..536f37a80 100644 --- a/include/users.h +++ b/include/users.h @@ -767,7 +767,7 @@ class userrec : public connection /** Handle socket event. * From EventHandler class. */ - void HandleEvent(EventType et); + void HandleEvent(EventType et, int errornum = 0); /** Default destructor */ diff --git a/src/dns.cpp b/src/dns.cpp index fb38a23b9..4248affae 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -944,7 +944,7 @@ int Resolver::GetId() } /** Process a socket read event */ -void DNS::HandleEvent(EventType et) +void DNS::HandleEvent(EventType et, int errornum) { ServerInstance->Log(DEBUG,"Marshall reads: %d",this->GetFd()); /* Fetch the id and result of the next available packet */ diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 53f3bb733..fe8b0b819 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -786,7 +786,7 @@ bool FileLogger::Readable() return false; } -void FileLogger::HandleEvent(EventType et) +void FileLogger::HandleEvent(EventType et, int errornum) { this->WriteLogLine(""); ServerInstance->SE->DelFd(this); diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 9b691fc7f..f8d5109fb 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -475,10 +475,12 @@ InspSocket::~InspSocket() this->Close(); } -void InspSocket::HandleEvent(EventType et) +void InspSocket::HandleEvent(EventType et, int errornum) { switch (et) { + case EVENT_ERROR: + break; case EVENT_READ: if (!this->Poll()) { diff --git a/src/socket.cpp b/src/socket.cpp index 4bf9dc30b..225b27733 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -51,7 +51,7 @@ ListenSocket::ListenSocket(InspIRCd* Instance, int sockfd, insp_sockaddr client, } } -void ListenSocket::HandleEvent(EventType et) +void ListenSocket::HandleEvent(EventType et, int errornum) { insp_sockaddr sock_us; // our port number socklen_t uslen; // length of our port number diff --git a/src/socketengine_epoll.cpp b/src/socketengine_epoll.cpp index c3c0c89a2..618f30592 100644 --- a/src/socketengine_epoll.cpp +++ b/src/socketengine_epoll.cpp @@ -130,10 +130,25 @@ int EPollEngine::GetRemainingFds() int EPollEngine::DispatchEvents() { + socklen_t codesize; + int errcode; int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 150); for (int j = 0; j < i; j++) { ServerInstance->Log(DEBUG,"Handle %s event on fd %d",events[j].events & EPOLLOUT ? "write" : "read", events[j].data.fd); + if (events[j].events & EPOLLHUP) + { + ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, 0); + continue; + } + if (events[j].events & EPOLLERR) + { + /* Get error number */ + if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) + errcode = errno; + ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, errcode); + continue; + } if (events[j].events & EPOLLOUT) { struct epoll_event ev; @@ -144,11 +159,13 @@ int EPollEngine::DispatchEvents() { ServerInstance->Log(DEBUG,"epoll: Could not reset fd %d!", events[j].data.fd); } - ref[events[j].data.fd]->HandleEvent(EVENT_WRITE); + if (ref[events[j].data.fd]) + ref[events[j].data.fd]->HandleEvent(EVENT_WRITE); } else { - ref[events[j].data.fd]->HandleEvent(EVENT_READ); + if (ref[events[j].data.fd]) + ref[events[j].data.fd]->HandleEvent(EVENT_READ); } } diff --git a/src/socketengine_select.cpp b/src/socketengine_select.cpp index 8b0379152..cdd1bdc3c 100644 --- a/src/socketengine_select.cpp +++ b/src/socketengine_select.cpp @@ -134,16 +134,21 @@ int SelectEngine::DispatchEvents() */ for (int i = 0; i < result; i++) { - ServerInstance->Log(DEBUG,"Handle %s event on fd %d",writeable[ev[i]->GetFd()] || !ev[i]->Readable() ? "write" : "read", ev[i]->GetFd()); - if (writeable[ev[i]->GetFd()]) + if (ev[i]) { - ev[i]->HandleEvent(EVENT_WRITE); - writeable[ev[i]->GetFd()] = false; - - } - else - { - ev[i]->HandleEvent(ev[i]->Readable() ? EVENT_READ : EVENT_WRITE); + ServerInstance->Log(DEBUG,"Handle %s event on fd %d",writeable[ev[i]->GetFd()] || !ev[i]->Readable() ? "write" : "read", ev[i]->GetFd()); + if (writeable[ev[i]->GetFd()]) + { + if (ev[i]) + ev[i]->HandleEvent(EVENT_WRITE); + writeable[ev[i]->GetFd()] = false; + + } + else + { + if (ev[i]) + ev[i]->HandleEvent(ev[i]->Readable() ? EVENT_READ : EVENT_WRITE); + } } } diff --git a/src/users.cpp b/src/users.cpp index 2c49e1ec7..6acbf137a 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -2026,7 +2026,7 @@ void userrec::ShowRULES() this->WriteServ("NOTICE %s :End of %s rules.",this->nick,ServerInstance->Config->ServerName); } -void userrec::HandleEvent(EventType et) +void userrec::HandleEvent(EventType et, int errornum) { /* WARNING: May delete this user! */ try |