Cygwin socket option SO_REUSEADDR operates unlike Linux
Corinna Vinschen
corinna-cygwin@cygwin.com
Mon Jan 15 20:03:00 GMT 2018
On Jan 13 13:39, Mark Geisert wrote:
> Corinna Vinschen wrote:
> > On Jan 13 00:36, Mark Geisert wrote:
> > > ~ ./bindtest
> > > 1st socket is 3
> > > 1st bind OK
> > > 1st connect OK
> > > 2nd socket is 3
> > > 2nd bind OK
> > > 2nd connect: Address already in use
> > >
> > > ~ ./bindtest
> > > 1st socket is 3
> > > 1st bind OK
> > > 1st connect: Address already in use
> > >
> > > On Fedora 27, running the same STC shows:
> > >
> > > [mark@lux ~]$ netstat -an|grep :111
> > > tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
> > > tcp6 0 0 :::111 :::* LISTEN
> > > udp 0 0 0.0.0.0:111 0.0.0.0:*
> > > udp6 0 0 :::111 :::*
> > > [mark@lux ~]$ ./bindtest
> > > 1st socket is 3
> > > 1st bind OK
> > > 1st connect OK
> > > 2nd socket is 3
> > > 2nd bind OK
> > > 2nd connect OK
> >
> > I can't reproduce this:
> >
> > $ uname -sr
> > Linux 4.14.13-300.fc27.x86_64
> > $ netstat -an|grep :111
> > tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
> > tcp6 0 0 :::111 :::* LISTEN
> > udp 0 0 0.0.0.0:111 0.0.0.0:*
> > udp6 0 0 :::111 :::*
> > $ ./bindtest
> > 1st socket is 3
> > 1st bind OK
> > 1st connect OK
> > 2nd socket is 3
> > 2nd bind OK
> > 2nd connect: Cannot assign requested address
> > [...]
> Rats. I'll have to investigate a couple of directions, deeper. It makes
> sense that connect() returns EADDRINUSE rather than bind() [...]
After some more digging it turns out that both of the above observations
on Linux are correct. I can reproduce the 2nd connect succeeding by
simply adding a `sleep(1)' after the first close. So it turns out that
Linux has a timing issue at socket cleanup which can be alleviated
by an extra sleep. I opened a case about this issue. EADDRNOTAVAIL
sounds a bit weird in this scenario, but it's kind of ok.
In terms of Cygwin, the EADDRINUSE is a completely different matter.
It turns out that the second connect fails because the first socket
connection is in TIME_WAIT state. This is not exactly correct in POSIX
terms. The TIME_WAIT connection should not disallow a new socket to
reuse the same local address. That's what we observe on Linux (apart from
the timing issue).
But here's the problem: Regardless if we actually use SO_REUSEADDR or
not, Windows sockets apparently disallows a subsequent connect to
succeed while the first socket is still in TIME_WAIT. I tweaked Cygwin
to enforce SO_REUSEADDR before bind, but connect still fails with
EADDRINUSE as long as the first socket is in TIME_WAIT.
It seems the code path for listen/accept is different here compared to
connect. Given that SO_REUSEADDR seems to cover mostly server side
scenarios, and given that I don't see this scenario discussed at all
in Steven's book, I wonder if bind/connect is a bit of a grey area.
Either way, the bottom line is that this is a WinSock restriction,
apparently. As of today, I don't see any way around that.
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20180115/e3a91684/attachment.sig>
More information about the Cygwin
mailing list