Skip to content

Commit

Permalink
fix crash after reading from fd > 1024 (#267)
Browse files Browse the repository at this point in the history
The socket selector holds a `seq` of per-descriptor data. When a reader
is registered, a pointer to a seq item is stored - when the `seq` grows,
this pointer becomes dangling and causes crashes like
status-im/nimbus-eth2#3521.

It turns out that there already exist two mechanisms for passing user
data around - this PR simply removes one of them, saving on memory usage
and removing the need to store pointers to the `seq` data that become
dangling on resize.
  • Loading branch information
arnetheduck authored Apr 11, 2022
1 parent ae2a877 commit bb4c329
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 82 deletions.
23 changes: 3 additions & 20 deletions chronos/asyncloop.nim
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ when defined(windows):
CompletionKey = ULONG_PTR

CompletionData* = object
fd*: AsyncFD
cb*: CallbackFunc
errCode*: OSErrorCode
bytesCount*: int32
Expand Down Expand Up @@ -500,17 +499,9 @@ elif unixPlatform:
type
AsyncFD* = distinct cint

CompletionData* = object
fd*: AsyncFD
udata*: pointer

PCompletionData* = ptr CompletionData

SelectorData* = object
reader*: AsyncCallback
rdata*: CompletionData
writer*: AsyncCallback
wdata*: CompletionData

PDispatcher* = ref object of PDispatcherBase
selector: Selector[SelectorData]
Expand Down Expand Up @@ -555,8 +546,6 @@ elif unixPlatform:
## Register file descriptor ``fd`` in thread's dispatcher.
let loop = getThreadDispatcher()
var data: SelectorData
data.rdata.fd = fd
data.wdata.fd = fd
loop.selector.registerHandle(int(fd), {}, data)

proc unregister*(fd: AsyncFD) {.raises: [Defect, CatchableError].} =
Expand All @@ -574,9 +563,8 @@ elif unixPlatform:
let loop = getThreadDispatcher()
var newEvents = {Event.Read}
withData(loop.selector, int(fd), adata) do:
let acb = AsyncCallback(function: cb, udata: addr adata.rdata)
let acb = AsyncCallback(function: cb, udata: udata)
adata.reader = acb
adata.rdata = CompletionData(fd: fd, udata: udata)
newEvents.incl(Event.Read)
if not(isNil(adata.writer.function)):
newEvents.incl(Event.Write)
Expand All @@ -592,7 +580,6 @@ elif unixPlatform:
withData(loop.selector, int(fd), adata) do:
# We need to clear `reader` data, because `selectors` don't do it
adata.reader = default(AsyncCallback)
# adata.rdata = CompletionData()
if not(isNil(adata.writer.function)):
newEvents.incl(Event.Write)
do:
Expand All @@ -606,9 +593,8 @@ elif unixPlatform:
let loop = getThreadDispatcher()
var newEvents = {Event.Write}
withData(loop.selector, int(fd), adata) do:
let acb = AsyncCallback(function: cb, udata: addr adata.wdata)
let acb = AsyncCallback(function: cb, udata: udata)
adata.writer = acb
adata.wdata = CompletionData(fd: fd, udata: udata)
newEvents.incl(Event.Write)
if not(isNil(adata.reader.function)):
newEvents.incl(Event.Read)
Expand All @@ -624,7 +610,6 @@ elif unixPlatform:
withData(loop.selector, int(fd), adata) do:
# We need to clear `writer` data, because `selectors` don't do it
adata.writer = default(AsyncCallback)
# adata.wdata = CompletionData()
if not(isNil(adata.reader.function)):
newEvents.incl(Event.Read)
do:
Expand Down Expand Up @@ -692,9 +677,7 @@ elif unixPlatform:
var data: SelectorData
result = loop.selector.registerSignal(signal, data)
withData(loop.selector, result, adata) do:
adata.reader = AsyncCallback(function: cb, udata: addr adata.rdata)
adata.rdata.fd = AsyncFD(result)
adata.rdata.udata = udata
adata.reader = AsyncCallback(function: cb, udata: udata)
do:
raise newException(ValueError, "File descriptor not registered.")

Expand Down
18 changes: 8 additions & 10 deletions chronos/transports/datagram.nim
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ elif defined(windows):
else:
## Initiation
transp.state.incl(WritePending)
let fd = SocketHandle(ovl.data.fd)
let fd = SocketHandle(transp.fd)
var vector = transp.queue.popFirst()
transp.setWriterWSABuffer(vector)
var ret: cint
Expand Down Expand Up @@ -258,7 +258,7 @@ elif defined(windows):
## Initiation
if transp.state * {ReadEof, ReadClosed, ReadError} == {}:
transp.state.incl(ReadPending)
let fd = SocketHandle(ovl.data.fd)
let fd = SocketHandle(transp.fd)
transp.rflag = 0
transp.ralen = SockLen(sizeof(Sockaddr_storage))
let ret = WSARecvFrom(fd, addr transp.rwsabuf, DWORD(1),
Expand Down Expand Up @@ -406,9 +406,9 @@ elif defined(windows):
result.udata = udata
result.state = {WritePaused}
result.future = newFuture[void]("datagram.transport")
result.rovl.data = CompletionData(fd: localSock, cb: readDatagramLoop,
result.rovl.data = CompletionData(cb: readDatagramLoop,
udata: cast[pointer](result))
result.wovl.data = CompletionData(fd: localSock, cb: writeDatagramLoop,
result.wovl.data = CompletionData(cb: writeDatagramLoop,
udata: cast[pointer](result))
result.rwsabuf = TWSABuf(buf: cast[cstring](addr result.buffer[0]),
len: int32(len(result.buffer)))
Expand All @@ -426,9 +426,8 @@ else:
proc readDatagramLoop(udata: pointer) {.raises: Defect.}=
var raddr: TransportAddress
doAssert(not isNil(udata))
var cdata = cast[ptr CompletionData](udata)
var transp = cast[DatagramTransport](cdata.udata)
let fd = SocketHandle(cdata.fd)
let transp = cast[DatagramTransport](udata)
let fd = SocketHandle(transp.fd)
if int(fd) == 0:
## This situation can be happen, when there events present
## after transport was closed.
Expand Down Expand Up @@ -459,9 +458,8 @@ else:
proc writeDatagramLoop(udata: pointer) =
var res: int
doAssert(not isNil(udata))
var cdata = cast[ptr CompletionData](udata)
var transp = cast[DatagramTransport](cdata.udata)
let fd = SocketHandle(cdata.fd)
var transp = cast[DatagramTransport](udata)
let fd = SocketHandle(transp.fd)
if int(fd) == 0:
## This situation can be happen, when there events present
## after transport was closed.
Expand Down
Loading

0 comments on commit bb4c329

Please sign in to comment.