Merge branch 'l04m33-async_callback_issue_0412-2' into devel
This commit is contained in:
commit
f3a0d702ae
3 changed files with 112 additions and 6 deletions
|
|
@ -972,9 +972,9 @@ else:
|
||||||
let data = PData(info.key.data)
|
let data = PData(info.key.data)
|
||||||
assert data.fd == info.key.fd.AsyncFD
|
assert data.fd == info.key.fd.AsyncFD
|
||||||
#echo("In poll ", data.fd.cint)
|
#echo("In poll ", data.fd.cint)
|
||||||
if EvError in info.events:
|
# There may be EvError here, but we handle them in callbacks,
|
||||||
closeSocket(data.fd)
|
# so that exceptions can be raised from `send(...)` and
|
||||||
continue
|
# `recv(...)` routines.
|
||||||
|
|
||||||
if EvRead in info.events:
|
if EvRead in info.events:
|
||||||
# Callback may add items to ``data.readCBs`` which causes issues if
|
# Callback may add items to ``data.readCBs`` which causes issues if
|
||||||
|
|
@ -1013,9 +1013,17 @@ else:
|
||||||
var retFuture = newFuture[void]("connect")
|
var retFuture = newFuture[void]("connect")
|
||||||
|
|
||||||
proc cb(fd: AsyncFD): bool =
|
proc cb(fd: AsyncFD): bool =
|
||||||
# We have connected.
|
var ret = SocketHandle(fd).getSockOptInt(cint(SOL_SOCKET), cint(SO_ERROR))
|
||||||
retFuture.complete()
|
if ret == 0:
|
||||||
return true
|
# We have connected.
|
||||||
|
retFuture.complete()
|
||||||
|
return true
|
||||||
|
elif ret == EINTR:
|
||||||
|
# interrupted, keep waiting
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
|
||||||
|
return true
|
||||||
|
|
||||||
assert getSockDomain(socket.SocketHandle) == domain
|
assert getSockDomain(socket.SocketHandle) == domain
|
||||||
var aiList = getAddrInfo(address, port, domain)
|
var aiList = getAddrInfo(address, port, domain)
|
||||||
|
|
|
||||||
33
tests/async/tasyncconnect.nim
Normal file
33
tests/async/tasyncconnect.nim
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
discard """
|
||||||
|
file: "tasyncconnect.nim"
|
||||||
|
exitcode: 1
|
||||||
|
outputsub: "Error: unhandled exception: Connection refused [Exception]"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import
|
||||||
|
asyncdispatch,
|
||||||
|
posix
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
testHost = "127.0.0.1"
|
||||||
|
testPort = Port(17357)
|
||||||
|
|
||||||
|
|
||||||
|
when defined(windows) or defined(nimdoc):
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
proc testAsyncConnect() {.async.} =
|
||||||
|
var s = newAsyncRawSocket()
|
||||||
|
|
||||||
|
await s.connect(testHost, testPort)
|
||||||
|
|
||||||
|
var peerAddr: SockAddr
|
||||||
|
var addrSize = Socklen(sizeof(peerAddr))
|
||||||
|
var ret = SocketHandle(s).getpeername(addr(peerAddr), addr(addrSize))
|
||||||
|
|
||||||
|
if ret < 0:
|
||||||
|
echo("`connect(...)` failed but no exception was raised.")
|
||||||
|
quit(2)
|
||||||
|
|
||||||
|
waitFor(testAsyncConnect())
|
||||||
65
tests/async/tasynceverror.nim
Normal file
65
tests/async/tasynceverror.nim
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
discard """
|
||||||
|
file: "tasynceverror.nim"
|
||||||
|
exitcode: 1
|
||||||
|
outputsub: "Error: unhandled exception: Connection reset by peer [Exception]"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import
|
||||||
|
asyncdispatch,
|
||||||
|
asyncnet,
|
||||||
|
rawsockets,
|
||||||
|
os
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
testHost = "127.0.0.1"
|
||||||
|
testPort = Port(17357)
|
||||||
|
|
||||||
|
|
||||||
|
when defined(windows) or defined(nimdoc):
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
proc createListenSocket(host: string, port: Port): TAsyncFD =
|
||||||
|
result = newAsyncRawSocket()
|
||||||
|
|
||||||
|
SocketHandle(result).setSockOptInt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||||
|
|
||||||
|
var aiList = getAddrInfo(host, port, AF_INET)
|
||||||
|
if SocketHandle(result).bindAddr(aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
|
||||||
|
dealloc(aiList)
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
dealloc(aiList)
|
||||||
|
|
||||||
|
if SocketHandle(result).listen(1) < 0'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
|
|
||||||
|
proc testAsyncSend() {.async.} =
|
||||||
|
var
|
||||||
|
ls = createListenSocket(testHost, testPort)
|
||||||
|
s = newAsyncSocket()
|
||||||
|
|
||||||
|
await s.connect(testHost, testPort)
|
||||||
|
|
||||||
|
var ps = await ls.accept()
|
||||||
|
SocketHandle(ls).close()
|
||||||
|
|
||||||
|
await ps.send("test 1", flags={})
|
||||||
|
s.close()
|
||||||
|
# This send should raise EPIPE
|
||||||
|
await ps.send("test 2", flags={})
|
||||||
|
SocketHandle(ps).close()
|
||||||
|
|
||||||
|
|
||||||
|
# The bug was, when the poll function handled EvError for us,
|
||||||
|
# our callbacks may never get executed, thus making the event
|
||||||
|
# loop block indefinitely. This is a timer to keep everything
|
||||||
|
# rolling. 400 ms is an arbitrary value, should be enough though.
|
||||||
|
proc timer() {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
echo("Timer expired.")
|
||||||
|
quit(2)
|
||||||
|
|
||||||
|
|
||||||
|
asyncCheck(testAsyncSend())
|
||||||
|
waitFor(timer())
|
||||||
Loading…
Add table
Add a link
Reference in a new issue