From 31286e45808936c857aee968027c3ae59e098884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Thu, 23 Nov 2017 22:57:03 +0100 Subject: [PATCH] Ensure the socket handle passed to callbacks is always valid on Posix. --- source/eventcore/drivers/posix/sockets.d | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index f6611ac..773fb24 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -148,14 +148,16 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets return fd; } - private void onConnect(FD sock) + private void onConnect(FD fd) { + auto sock = cast(StreamSocketFD)fd; + auto l = lockHandle(sock); m_loop.setNotifyCallback!(EventType.write)(sock, null); with (m_loop.m_fds[sock].streamSocket) { state = ConnectionState.connected; auto cb = connectCallback; connectCallback = null; - if (cb) cb(cast(StreamSocketFD)sock, ConnectStatus.connected); + if (cb) cb(sock, ConnectStatus.connected); } } @@ -349,6 +351,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets void finalize()(IOStatus status) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.read)(socket, null); //m_fds[fd].readBuffer = null; slot.readCallback(socket, status, slot.bytesRead); @@ -446,6 +449,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets if (ret < 0) { auto err = getSocketError(); if (!err.among!(EAGAIN, EINPROGRESS)) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.write)(socket, null); slot.writeCallback(socket, IOStatus.error, slot.bytesRead); return; @@ -456,6 +460,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets slot.bytesWritten += ret; slot.writeBuffer = slot.writeBuffer[ret .. $]; if (slot.writeMode != IOMode.all || slot.writeBuffer.length == 0) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.write)(socket, null); slot.writeCallback(cast(StreamSocketFD)socket, IOStatus.ok, slot.bytesWritten); return; @@ -506,6 +511,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets void finalize()(IOStatus status) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.read)(socket, null); //m_fds[fd].readBuffer = null; slot.readCallback(socket, status, 0); @@ -683,12 +689,14 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets if (ret < 0) { auto err = getSocketError(); if (!err.among!(EAGAIN, EINPROGRESS)) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.read)(socket, null); slot.readCallback(socket, IOStatus.error, 0, null); return; } } + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.read)(socket, null); scope src_addrc = new RefAddress(() @trusted { return cast(sockaddr*)&src_addr; } (), src_addr.sizeof); () @trusted { return cast(DatagramIOCallback)slot.readCallback; } ()(socket, IOStatus.ok, ret, src_addrc); @@ -754,12 +762,14 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets if (ret < 0) { auto err = getSocketError(); if (!err.among!(EAGAIN, EINPROGRESS)) { + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.write)(socket, null); () @trusted { return cast(DatagramIOCallback)slot.writeCallback; } ()(socket, IOStatus.error, 0, null); return; } } + auto l = lockHandle(socket); m_loop.setNotifyCallback!(EventType.write)(socket, null); () @trusted { return cast(DatagramIOCallback)slot.writeCallback; } ()(socket, IOStatus.ok, ret, null); } @@ -844,6 +854,19 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets } return sock; } + + // keeps a scoped reference to a handle to avoid it getting destroyed + private auto lockHandle(H)(H handle) + { + addRef(handle); + static struct R { + PosixEventDriverSockets drv; + H handle; + @disable this(this); + ~this() { drv.releaseRef(handle); } + } + return R(this, handle); + } } package struct StreamSocketSlot {