[Python-Dev] socket.SOL_REUSEADDR: different semantics between Windows vs Unix (or why test_asynchat is sometimes dying on Windows) (original) (raw)

Jean-Paul Calderone exarkun at divmod.com
Sat Apr 5 00:01:53 CEST 2008


On Fri, 4 Apr 2008 13:24:49 -0700, Trent Nelson <tnelson at onresolve.com> wrote:

Interesting results! I committed the patch to testsocket.py in r62152. I was expecting all other platforms except for Windows to behave consistently (i.e. pass). That is, given the following:

import socket host = '127.0.0.1' sock = socket.socket(socket.AFINET, socket.SOCKSTREAM) sock.bind((host, 0)) port = sock.getsockname()[1] sock.close() del sock sock1 = socket.socket(socket.AFINET, socket.SOCKSTREAM) sock1.setsockopt(socket.SOLSOCKET, socket.SOREUSEADDR, 1) sock1.bind((host, port)) sock2 = socket.socket(socket.AFINET, socket.SOCKSTREAM) sock2.setsockopt(socket.SOLSOCKET, socket.SOREUSEADDR, 1) sock2.bind((host, port)) ^^^^ ....the second bind should fail with EADDRINUSE, at least according to the 'SOREUSEADDR and SOREUSEPORT Socket Options' section in chapter 7.5 of Stevens' UNIX Network Programming Volume 1 (2nd Ed): "With TCP, we are never able to start multiple servers that bind the same IP address and same port: a completely duplicate binding. That is, we cannot start one server that binds 198.69.10.2 port 80 and start another that also binds 198.69.10.2 port 80, even if we set the SOREUSEADDR socket option for the second server." The results: both Windows and Linux fail the patched test; none of the buildbots for either platform encountered an EADDRINUSE socket.error after the second bind(). FreeBSD, OS X, Solaris and Tru64 pass the test -- EADDRINUSE is raised on the second bind. (Interesting that all the ones that passed have a BSD lineage.)

Notice that the quoted text explains that you cannot start multiple servers that etc. Since you didn't call listen on either socket, it's arguable that you didn't start any servers, so there should be no surprise regarding the behavior. Try adding listen calls at various places in the example and you'll see something different happen.

FWIW, AIUI, SO_REUSEADDR behaves just as described in the above quote on Linux/BSD/UNIX/etc. On Windows, however, that option actually means something quite different. It means that the address should be stolen from any process which happens to be using it at the moment.

There is another option, SO_EXCLUSIVEADDRUSE, only on Windows I think, which, AIUI, makes it impossible for another process to steal the port using SO_REUSEADDR.

Hope this helps,

Jean-Paul



More information about the Python-Dev mailing list