Why doesn't uv_tcp_bind fail

74 views
Skip to first unread message

Iñaki Baz Castillo

unread,
Mar 14, 2019, 10:43:33 PM3/14/19
to li...@googlegroups.com
According to the uv_tcp_bind doc:

> When the port is already taken, you can expect to see an UV_EADDRINUSE error from either uv_tcp_bind(), uv_listen() or uv_tcp_connect(). That is, a successful call to this function does not guarantee that the call to uv_listen() or uv_tcp_connect() will succeed as well.

Indeed I confirm that, at least in Linux, uv_tcp_bind may succeed
while the next call to uv_listen may fail with UV_EADDRINUSE.

May I know why uv_tcp_bind did not fail? This is, why is it designed that way?


--
Iñaki Baz Castillo
<i...@aliax.net>

Iñaki Baz Castillo

unread,
Mar 14, 2019, 10:51:13 PM3/14/19
to li...@googlegroups.com
On Fri, 15 Mar 2019 at 03:43, Iñaki Baz Castillo <i...@aliax.net> wrote:
> Indeed I confirm that, at least in Linux, uv_tcp_bind may succeed
> while the next call to uv_listen may fail with UV_EADDRINUSE.

In fact this is being super problematic for me. I have a "helper" that
gets a random TCP port and returns the corresponding uv_handle. It
just checks whether uv_tcp_bind() fails or not (here the problem, of
course). and then I use the theoretically available uv_handle into
another class in which I call uv_listen() with it.

https://github.com/versatica/mediasoup/blob/v3/worker/src/RTC/PortManager.cpp?ts=2#L182
https://github.com/versatica/mediasoup/blob/v3/worker/src/handles/TcpServer.cpp?ts=2#L37

I'm setting the corresponding uv_connection_cb in the second file, I
cannot set it in the first one (in the "helper"). Is there any
workaround for this? I mean something such as doing both uv_tcp_bind()
and uv_listen() in the "helper" and, if ok, un-listen the uv_handle
and return it (so the second file can run uv_listen() with it).

Iñaki Baz Castillo

unread,
Mar 14, 2019, 10:56:37 PM3/14/19
to li...@googlegroups.com
On Fri, 15 Mar 2019 at 03:50, Iñaki Baz Castillo <i...@aliax.net> wrote:
> I'm setting the corresponding uv_connection_cb in the second file, I
> cannot set it in the first one (in the "helper"). Is there any
> workaround for this? I mean something such as doing both uv_tcp_bind()
> and uv_listen() in the "helper" and, if ok, un-listen the uv_handle
> and return it (so the second file can run uv_listen() with it).

Can I call twice to uv_listen() with different uv_connection_cb? That
would make me happy :)

Saúl Ibarra Corretgé

unread,
Mar 15, 2019, 7:35:19 AM3/15/19
to li...@googlegroups.com
You can, but the second time will fail if you were already listening.

--
Saúl

Ben Noordhuis

unread,
Mar 15, 2019, 8:31:01 AM3/15/19
to li...@googlegroups.com
That's not a libuv design, it's because some operating systems don't
commit the port until it's actually used - i.e., until it listens or
connects to somewhere.

The documentation contains a small lie: uv_tcp_bind() defers
EADDRINUSE error reporting to uv_listen() and uv_tcp_connect().
Corrected in https://github.com/libuv/libuv/pull/2218.

Iñaki Baz Castillo

unread,
Mar 15, 2019, 9:35:19 AM3/15/19
to li...@googlegroups.com
On Fri, 15 Mar 2019 at 12:35, Saúl Ibarra Corretgé <sag...@gmail.com> wrote:
> > Can I call twice to uv_listen() with different uv_connection_cb? That
> > would make me happy :)
>
> You can, but the second time will fail if you were already listening.

I just confirm that it does not fail at all. Note: I'm calling
uv_listen() twice in the same loop iteration.

Iñaki Baz Castillo

unread,
Mar 15, 2019, 9:38:22 AM3/15/19
to li...@googlegroups.com
On Fri, 15 Mar 2019 at 13:31, Ben Noordhuis <in...@bnoordhuis.nl> wrote:
> > May I know why uv_tcp_bind did not fail? This is, why is it designed that way?
>
> That's not a libuv design, it's because some operating systems don't
> commit the port until it's actually used - i.e., until it listens or
> connects to somewhere.

Clear.

> The documentation contains a small lie: uv_tcp_bind() defers
> EADDRINUSE error reporting to uv_listen() and uv_tcp_connect().
> Corrected in https://github.com/libuv/libuv/pull/2218.

Ok.

So in order to "fix" my use case problem (I cannot set the definitive
uv_connection_cb in the C file in which I call to uv_tcp_bind(), I see
two approaches:

1) Calling uv_listen() twice (with a different uv_connection_cb). I do
it currently in the same loop iteration and it works.

2) "Manually" change the uv_connection_cb in the uv_handle struct.
This is not public API AFAIK.

Which is the best approach? Is there anyone better?

Saúl Ibarra Corretgé

unread,
Mar 15, 2019, 9:49:05 AM3/15/19
to li...@googlegroups.com
On 15/03/2019 14:35, Iñaki Baz Castillo wrote:
> On Fri, 15 Mar 2019 at 12:35, Saúl Ibarra Corretgé <sag...@gmail.com> wrote:
>>> Can I call twice to uv_listen() with different uv_connection_cb? That
>>> would make me happy :)
>>
>> You can, but the second time will fail if you were already listening.
>
> I just confirm that it does not fail at all. Note: I'm calling
> uv_listen() twice in the same loop iteration.
>
>

Yeah, my bad. I mistakenly thought listen(2) would give EALREADY error,
but that's connect(2).


--
Saúl

Iñaki Baz Castillo

unread,
Mar 15, 2019, 9:54:33 AM3/15/19
to li...@googlegroups.com
Ok, so then it's safe to call uv_listen() twice. Thanks :)
Reply all
Reply to author
Forward
0 new messages