I'm currently building a server using asyncnet. The actual functionality of it is not important, but what is important is that I need to disconnect idle sockets after a certain period of inactivity. What I have noticed is that calling close(AsyncSocket) does not have the same effect as an actual disconnection from the client socket.
When I first tested my code, close(AsyncNet) seemed to cause recv to hang, instead of returning an incomplete or empty string like it is advertised to do. After some further testing, I discovered that seemingly no asyncnet procs were returning, and were all hanging. My server socket accept loop was hanging on accept(AsyncSocket), and recv was still not returning either. None of this behavior was present when a natural disconnect occurred, so I'm very confused as to what the difference is between a real, natural disconnect and a call to close(AsyncSocket).
One other thing I noticed was that the official documentation for asyncnet did not accurately describe close(AsyncSocket), and it claimed that it returned a Future, but the current version does not return anything, and presumably closes the connection instantly, or at least seems that way. https://nim-lang.org/docs/asyncnet.html#close%2CAsyncSocket
Is there some way to actually trigger the behavior of a natural disconnect when closing a socket? I can't leave these sockets open for memory and other reasons during long periods of inactivity. This seems to either be a bug, or something that I have missed. At the moment I believe it might be due to a bug relating to a deadlock, because several unrelated procs also hang.
I have written an example to reproduce what I'm talking about. The server can be tested using netcat or some other network tool. Just connect to the server, and after a few seconds it will close the socket successfully, but it will then hang. https://play.nim-lang.org/#ix=3PEs
Thanks.
Close being called using withTimeout seems to work as expected. This issue seems to stem from when the close call is being made, and from where. This still presents the issue of closing clients later by force, but maybe it's a nothingburger. Still, does anyone have any ideas why the way I call close hangs everything?
Here is the code using withTimeout in the initClientAndLoop which works:
echo "Receiving..."
let fut = conn.recv(5)
if await withTimeout(fut, IDLE_TIMEOUT):
let res = await fut
echo fmt"Received {res.len} bytes"
if res == "quit\n":
conn.close()
echo (await conn.recv(1)).len
break
else:
echo "Timed out"
conn.close()
return