X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsocketengines%2Fsocketengine_poll.cpp;h=d25f21d9462d8b40bec004d2ba956c7f25b319bf;hb=fe41ae3e8194d531e6e7427ec30d3fb58871498c;hp=0112b7d2fb5c431e7a512ba585f02653021b7bc6;hpb=3752b3f59d5216d7dc6221a361efc76b9ad2273d;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index 0112b7d2f..d25f21d94 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -1,10 +1,12 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2014 Adam - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2009 Uli Schlachter - * Copyright (C) 2009 Craig Edwards + * Copyright (C) 2014-2015 Attila Molnar + * Copyright (C) 2014, 2017 Adam + * Copyright (C) 2013, 2016-2017 Sadie Powell + * Copyright (C) 2012 Robby + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2009 Uli Schlachter * Copyright (C) 2008 Robin Burchell * * This file is part of InspIRCd. InspIRCd is free software: you can @@ -21,69 +23,34 @@ */ -#ifndef SOCKETENGINE_POLL -#define SOCKETENGINE_POLL - -#include -#include -#include -#include -#include "exitcodes.h" #include "inspircd.h" -#include "socketengine.h" - -#ifndef _WIN32 -# ifndef __USE_XOPEN -# define __USE_XOPEN /* fuck every fucking OS ever made. needed by poll.h to work.*/ -# endif -# include -# include -# include -#else -# define struct pollfd WSAPOLLFD -# define poll WSAPoll -#endif - -class InspIRCd; + +#include +#include /** A specialisation of the SocketEngine class, designed to use poll(). */ -class PollEngine : public SocketEngine +namespace { -private: /** These are used by poll() to hold socket events */ - std::vector events; + std::vector events(16); /** This vector maps fds to an index in the events array. */ - std::vector fd_mappings; -public: - /** Create a new PollEngine - */ - PollEngine(); - virtual bool AddFd(EventHandler* eh, int event_mask); - virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask); - virtual void DelFd(EventHandler* eh); - virtual int DispatchEvents(); - virtual std::string GetName(); -}; + std::vector fd_mappings(16, -1); +} -#endif +void SocketEngine::Init() +{ + LookupMaxFds(); +} -PollEngine::PollEngine() : events(1), fd_mappings(1) +void SocketEngine::Deinit() +{ +} + +void SocketEngine::RecoverFromFork() { - CurrentSetSize = 0; - struct rlimit limits; - if (!getrlimit(RLIMIT_NOFILE, &limits)) - { - MAX_DESCRIPTORS = limits.rlim_cur; - } - else - { - ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno)); - std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl; - ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); - } } static int mask_to_poll(int event_mask) @@ -96,12 +63,12 @@ static int mask_to_poll(int event_mask) return rv; } -bool PollEngine::AddFd(EventHandler* eh, int event_mask) +bool SocketEngine::AddFd(EventHandler* eh, int event_mask) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > GetMaxFds() - 1)) + if (fd < 0) { - ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds()); + ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d)", fd); return false; } @@ -111,14 +78,14 @@ bool PollEngine::AddFd(EventHandler* eh, int event_mask) return false; } - if (!SocketEngine::AddFd(eh)) + unsigned int index = CurrentSetSize; + + if (!SocketEngine::AddFdRef(eh)) { ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd); return false; } - unsigned int index = CurrentSetSize; - while (static_cast(fd) >= fd_mappings.size()) fd_mappings.resize(fd_mappings.size() * 2, -1); fd_mappings[fd] = index; @@ -128,12 +95,11 @@ bool PollEngine::AddFd(EventHandler* eh, int event_mask) events[index].events = mask_to_poll(event_mask); ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d (%d; index %d)", fd, events[index].events, index); - SocketEngine::SetEventMask(eh, event_mask); - CurrentSetSize++; + eh->SetEventMask(event_mask); return true; } -void PollEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask) +void SocketEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask) { int fd = eh->GetFd(); if (fd < 0 || static_cast(fd) >= fd_mappings.size() || fd_mappings[fd] == -1) @@ -145,12 +111,12 @@ void PollEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask) events[fd_mappings[fd]].events = mask_to_poll(new_mask); } -void PollEngine::DelFd(EventHandler* eh) +void SocketEngine::DelFd(EventHandler* eh) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if (fd < 0) { - ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds()); + ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d)", fd); return; } @@ -182,77 +148,70 @@ void PollEngine::DelFd(EventHandler* eh) events[last_index].fd = 0; events[last_index].events = 0; - SocketEngine::DelFd(eh); - - CurrentSetSize--; + SocketEngine::DelFdRef(eh); ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d (index: %d) " "(Filled gap with: %d (index: %d))", fd, index, last_fd, last_index); } -int PollEngine::DispatchEvents() +int SocketEngine::DispatchEvents() { int i = poll(&events[0], CurrentSetSize, 1000); - int index; - socklen_t codesize = sizeof(int); - int errcode; int processed = 0; ServerInstance->UpdateTime(); - for (index = 0; index < CurrentSetSize && processed < i; index++) + for (size_t index = 0; index < CurrentSetSize && processed < i; index++) { struct pollfd& pfd = events[index]; - if (pfd.revents) + // Copy these in case the vector gets resized and pfd invalidated + const int fd = pfd.fd; + const short revents = pfd.revents; + + if (revents) processed++; - EventHandler* eh = GetRef(pfd.fd); + EventHandler* eh = GetRef(fd); if (!eh) continue; - if (pfd.revents & POLLHUP) + if (revents & POLLHUP) { - eh->HandleEvent(EVENT_ERROR, 0); + eh->OnEventHandlerError(0); continue; } - if (pfd.revents & POLLERR) + if (revents & POLLERR) { // Get error number - if (getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) + socklen_t codesize = sizeof(int); + int errcode; + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; - eh->HandleEvent(EVENT_ERROR, errcode); + eh->OnEventHandlerError(errcode); continue; } - if (pfd.revents & POLLIN) + if (revents & POLLIN) { - SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK); - eh->HandleEvent(EVENT_READ); - if (eh != GetRef(pfd.fd)) + eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK); + eh->OnEventHandlerRead(); + if (eh != GetRef(fd)) // whoops, deleted out from under us continue; } - if (pfd.revents & POLLOUT) + if (revents & POLLOUT) { int mask = eh->GetEventMask(); mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE); - SetEventMask(eh, mask); - pfd.events = mask_to_poll(mask); - eh->HandleEvent(EVENT_WRITE); + eh->SetEventMask(mask); + + // The vector could've been resized, reference can be invalid by now; don't use it + events[index].events = mask_to_poll(mask); + eh->OnEventHandlerWrite(); } } return i; } - -std::string PollEngine::GetName() -{ - return "poll"; -} - -SocketEngine* CreateSocketEngine() -{ - return new PollEngine; -}