Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
IO::Socket::Async.listen only tappable once. Binding address on tap inhibits use of Supply methods #2733
The supply returned from IO::Socket::Async.listen can only be tapped once without error. Calling methods that directly or indirectly tap subsequent times causes a 'address already in use' error.
I would expect the socket to
The docs suggest that the IO::Socket::Async does not start to listen until the supply returned from .listen is tapped. Tapping a second time or using .wait (indirect tap) causes the 'address already in use' error.
Output from this code with perl6 --ll-exception is :
address already in use
from :1 (/opt/local/share/perl6/runtime/perl6.moarvm:)
Rakudo version 2018.12 built on MoarVM version 2018.12
I knew about this behaviour but didn't consider adding it as part of my grant work on networking support. Depending on what other people think, I could make this work at some point within the next couple of months.
Running socat as a server
Adding a single .tap or .wait on the Socket supply after the .listen in this situation does throw the error.
As for what you want from the expected behaviour, I think it's reasonable to expect, but one comment:
Servers should never drop connections for a reason like this. Using
Perhaps the .listen method should basically call the system listen(). This will queue connections in the kernel until the system accept() is called.
On the first .tap method called, this eventually calls the system accept(), and starts dequeuing connections from the kernel, and feeding into the Supply.
This is opposed to .listen method immediately calling system accept() and then basically having to throw away or preserve the dequeued connections until the .tap method is called. I feel this conflates the intent of .listen and .tap and also is potentially double handling the connection queuing for no real gain.
This isn't quite how it'd work with MoarVM since it uses libuv for async sockets. What could be done is have
I don't have much experience with libuv. Yes it sounds like it could be much trickier! I'm pretty new to rakudo / Perl6. Would you mind pointing me to the code that implements this?
I have even less experience with Java, but a quick websearch regarding
Some sort or state management might need to be implemented then when tapping?
Or am I continuing to over simply the issue?
I'm not sure. There would need to be some refactoring done so sockets received from the VM can be emitted to any taps that exist since the
The current behavior is correct, and consistent with the overall design of
There are two kinds of
Since it's permissible to pass
While handling multiple concurrent connections is indeed a common requirement, that is easily handled:
It seems highly unlikely that the actual processing of new connections themselves would be a bottleneck.
Will almost never be what was intended; they work by accident but waste resources on a live
Though for most folks it'd be better if they just learned this way:
And the docs already show this way of doing things when dealing with async sockets, which hopefully means in the common case people will follow the structured programming approach rather than confuse themselves with the unstructured one. :-)
Since the behavior in Rakudo seems correct and the docs seem to show the right way already, I don't think there's much more to be done than to close this issue. It's somewhat tempting to open one pondering deprecation of