> I think I fixed this in r3360. I was able to reproduce the errors
> from Bob's script on my Ubuntu machine and they're fixed by that
> I'm a little perplexed as to how it fixes it though. The change just
> fixes a bug where the client Java Socket returned from accept on a
> ServerSocket would have its setReuseAddress value set to false
> regardless of its initial value; now it keeps the value in the Socket.
> It seems like if a ServerSocket has reuseAddress as true, its client
> Sockets will have reuseAddress true as well.
Well done Charlie, I think you nailed it.
The SO_REUSEADDR status of 'accept'ed sockets is unclear in the java
The javadoc for the java.net.Socket.setReuseAddress() method states that
"When a Socket is created the initial setting of SO_REUSEADDR is
disabled". This is the case for the docs for 1.4.x, 1.5 and 1.6
However, that appears not to apply to sockets created by 'accept'ing
incoming connections, which seem to inherit the SO_REUSEADDR value of
their parent ServerSocket.
Furthermore, the documentation states that "The behaviour when
SO_REUSEADDR is enabled or disabled after a socket is bound (See
isBound()) is not defined". It appears that we are experiencing
different behaviour across platforms, because setting SO_REUSEADDR after
the creation (and implicit binding) of the 'accept'ed client socket
gives different behaviour on different platforms.
Windows and Mac seem to permit re-binding of the server socket, as long
as SO_REUSEADDR is set on the server socket; the SO_REUSEADDR value of
the 'accept'ed clients seems not to matter.
Contrarily, Linux seems to NOT permit re-binding of the server socket if
an 'accept'ed client socket has SO_REUSEADDR set to false after it is
created (and presumably bound), and even if the server socket has an
SO_REUSEADDR setting of true.
Perhaps it depends on the address to which the newly 'accept'ed socket
is bound? If it is (locally) bound to the same port as the server
socket, then some platforms may consider that a clash of ports, whereas
other don't, because one is a server and one is a client. I know that
Windows uses a different model for permitting exclusive access to a
given port: "In Windows 2000 SP1 Microsoft added the SO_EXCLUSIVEADDRUSE
which prevents multiple sockets from binding to the same address/port".
In order to try and get to the bottom of this bug, I wrote a small java
program which uses the exact same sequence of operations as the socket
and test_socket modules, in order to reproduce the problem. The code is
attached. But I wasn't able to recreate the problem; the code ran
smoothly on Windows and Red Hat, on both Sun and IBM JVMs.
But now I have amended that code to re/set the SO_REUSEADDR flag on
'accept'ed client sockets (as well as display the value that they
already have). The code, by default, leaves the value of the
SO_REUSEADDR flag unchanged, which is the same behaviour as jython
sockets have after Charlie made that change.
So that java code *should* not fail with the same BindException as was
troubling the test suite, when run on Linux. When I run it on Windows,
it never fails.
In order to reproduce the binding problems, pass any parameter to the
class when it is run on the command line. The presence of any parameter
will cause the resetting of the SO_REUSEADDR flag on all 'accept'ed
sockets, which is the behaviour that jython sockets used to have before
Charlies fix. So passing a parameter to this class should cause it to
fail with BindExceptions. But I can only test it here at home on Windows
(where it never fails); I don't have a Linux box here. I will run it on
Red Hat in work on Monday; I expect it will reproduce the problem.
Lastly, the code displays the bound status of the 'accept'ed client
socket. This value is always displayed as bound on Windows, to the same
port as the server socket; I would interested to know the bound status
differs on other platforms.
Good work Charlie! And many thanks to Raghu, Bob and Pekka for helping
get to the bottom of this.
All the best,