diff options
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 4 | ||||
-rw-r--r-- | src/socketengines/socketengine_kqueue.cpp | 12 | ||||
-rw-r--r-- | src/socketengines/socketengine_poll.cpp | 24 | ||||
-rw-r--r-- | src/socketengines/socketengine_ports.cpp | 12 |
4 files changed, 33 insertions, 19 deletions
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index af58cb026..b9563ed2b 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -54,6 +54,7 @@ public: EPollEngine::EPollEngine() : events(1) { + CurrentSetSize = 0; int max = ulimit(4, 0); if (max > 0) { @@ -193,7 +194,8 @@ int EPollEngine::DispatchEvents() for (int j = 0; j < i; j++) { - struct epoll_event& ev = events[j]; + // Copy these in case the vector gets resized and ev invalidated + const epoll_event ev = events[j]; EventHandler* eh = GetRef(ev.data.fd); if (!eh) diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index 81addd1c2..99d4236e9 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -219,7 +219,11 @@ int KQueueEngine::DispatchEvents() { struct kevent& kev = ke_list[j]; - EventHandler* eh = GetRef(kev.ident); + // Copy these in case the vector gets resized and kev invalidated + const int fd = kev.ident; + const short filter = kev.filter; + + EventHandler* eh = GetRef(fd); if (!eh) continue; @@ -229,7 +233,7 @@ int KQueueEngine::DispatchEvents() eh->HandleEvent(EVENT_ERROR, kev.fflags); continue; } - if (kev.filter == EVFILT_WRITE) + if (filter == EVFILT_WRITE) { WriteEvents++; /* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE, @@ -240,11 +244,11 @@ int KQueueEngine::DispatchEvents() SetEventMask(eh, eh->GetEventMask() & ~bits_to_clr); eh->HandleEvent(EVENT_WRITE); - if (eh != GetRef(kev.ident)) + if (eh != GetRef(fd)) // whoops, deleted out from under us continue; } - if (kev.filter == EVFILT_READ) + if (filter == EVFILT_READ) { ReadEvents++; SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK); diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index 722555510..2919988c0 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -196,43 +196,49 @@ int PollEngine::DispatchEvents() { 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); continue; } - if (pfd.revents & POLLERR) + if (revents & POLLERR) { // Get error number - if (getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; eh->HandleEvent(EVENT_ERROR, 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)) + 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); + + // The vector could've been resized, reference can be invalid by now; don't use it + events[index].events = mask_to_poll(mask); eh->HandleEvent(EVENT_WRITE); } } diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index 569155021..098e75116 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -162,27 +162,29 @@ int PortsEngine::DispatchEvents() if (ev.portev_source != PORT_SOURCE_FD) continue; - int fd = ev.portev_object; + // Copy these in case the vector gets resized and ev invalidated + const int fd = ev.portev_object; + const int portev_events = ev.portev_events; EventHandler* eh = GetRef(fd); if (!eh) continue; int mask = eh->GetEventMask(); - if (ev.portev_events & POLLWRNORM) + if (portev_events & POLLWRNORM) mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE); - if (ev.portev_events & POLLRDNORM) + if (portev_events & POLLRDNORM) mask &= ~FD_READ_WILL_BLOCK; // reinsert port for next time around, pretending to be one-shot for writes SetEventMask(eh, mask); port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh); - if (ev.portev_events & POLLRDNORM) + if (portev_events & POLLRDNORM) { ReadEvents++; eh->HandleEvent(EVENT_READ); if (eh != GetRef(fd)) continue; } - if (ev.portev_events & POLLWRNORM) + if (portev_events & POLLWRNORM) { WriteEvents++; eh->HandleEvent(EVENT_WRITE); |