Why does OS X allow listening on the same TCP port twice?
Asked Answered
F

1

12

I was trying to debug port allocation problems in Jenkins on OS X by listening to certain ports with netcat, which led to some weird results.


In a terminal on OS X 10.8.2:

$ uname -rs
Darwin 12.2.1

$ nc -l 54321

Then in an second terminal:

$ nc -l 54321

And in a third terminal, lsof shows that both instances have bound to the same port:

$ lsof -i | grep 54321
nc  70706 chris    3u  IPv4 0x55618c024692f4d1      0t0  TCP *:54321 (LISTEN)
nc  70769 chris    3u  IPv4 0x55618c0232cb8661      0t0  TCP *:54321 (LISTEN)

On Linux:

First terminal:

$ uname -rs
Linux 3.2.0-34-generic

$ nc -l 54321

Second terminal:

$ nc -l 54321
nc: Address already in use

Why doesn't OS X also report that the address is already in use?

Farleigh answered 5/12, 2012 at 15:44 Comment(4)
I don't know the lsof -i output syntaxis, but what are 0x55618c024692f4d1 and 0x55618c0232cb8661? If it are IP addresses, then it's obviously because the listener was bound to a specific IP address and not the "any" address.Vallery
They're meaningless memory addresses. The only purpose they have is to identify that these are two distinct sockets (e.g, not the result of a fork() or dup()).Kellum
Running lsof -i gives me 27 unique values for that field ("DEVICE"); I believe it's a memory address. The final column shows that the sockets are bound to *.Farleigh
Of course, and they're too long to be IPv4 addresses anyway. I stand corrected. :-)Vallery
G
10

The binary on OS X is setting the SO_REUSEPORT socket option, which allows completely duplicate bindings (setsockopt on OS X). You can verify this using dtrace on OS X.

The netcat binary on Linux does not do this, so you get a bind error as expected. Again, you can verify that using strace. I belive SO_REUSEPORT is deprecated, or not even available on newer Linux kernels.

Giefer answered 6/12, 2012 at 1:57 Comment(3)
Thanks for the info! That also explains why if another piece of software was running, nc did complain that the port was already in use.Farleigh
For info, the SO_REUSEPORT socket option was added to Linux 3.9: lwn.net/Articles/542629Farleigh
This is helpful however can you provide an example of dtrace which can help a programmer confirm this? The examples I've found online are sparse and a bit hard to understand, especially if that programmer is unfamiliar with C. This makes it harder to identify for those dealing with this issue downstream such as in an interpreted / JIT fashion.Coalfish

© 2022 - 2024 — McMap. All rights reserved.