From: noreply@... Date: 2005-11-24T01:46:01+09:00 Subject: [ ruby-Bugs-2872 ] TCPServer should not use SO_REUSEADDR in Cygwin port Bugs item #2872, was opened at 2005-11-23 11:36 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1698&aid=2872&group_id=426 Category: Standard Library Group: None Status: Open Resolution: None Priority: 3 Submitted By: Andrew Wason (awason) Assigned to: Nobody (None) Summary: TCPServer should not use SO_REUSEADDR in Cygwin port Initial Comment: SO_REUSEADDR behaves strangely under Win32, it allows multiple LISTENs on the same port with indeterminate results. On other platforms SO_REUSEADDR only allows binding to a port not in use or in the TIME_WAIT state. "This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state), go ahead and reuse it anyway. If it is busy, but with another state, you will still get an address already in use error." http://www.unixguide.net/network/socketfaq/4.5.shtml "Once the second sockey has successfully bound, the behvaior for all sockets bound to that port is indeterminate." http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/using_so_reuseaddr_and_so_exclusiveaddruse.asp In Ruby 1.8.2/1.8.3, ext/socket/socket.c does not set SO_REUSEADDR for TCPServer if _WIN32 is defined, so things work normally in the i386-mswin32 builds. But the i386-cygwin builds do set SO_REUSEADDR and so weird things can happen. So in socket.c init_inetsock_internal(), this code should also not be compiled for Cygwin (__CYGWIN__): if (type == INET_SERVER) { #ifndef _WIN32 status = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&status, sizeof(status)); #endif Here is a comparison of current mswin32 and cygwin behaviors: == Cygwin, 2 process actively listening to same port $ ruby -v ruby 1.8.3 (2005-09-21) [i386-cygwin] # From two different consoles: $ ruby -rsocket -e 'TCPServer.new("localhost", 3900).accept' $ ruby -rsocket -e 'TCPServer.new("localhost", 3900).accept' $ netstat -a -p TCP | grep 3900 TCP jello:3900 jello:0 LISTENING TCP jello:3900 jello:0 LISTENING == MSWIN32, 2nd process correctly fails with EADDRINUSE C:\>ruby -v ruby 1.8.2 (2004-12-25) [i386-mswin32] # From two different consoles: C:\>ruby -rsocket -e 'TCPServer.new("localhost", 3900).accept' C:\>ruby -rsocket -e 'TCPServer.new("localhost", 3900).accept' -e:1:in `initialize': Only one usage of each socket address (protocol/network address/port) is normally permitted. - bind(2) (Errno::EADDRINUSE) from -e:1:in `new' from -e:1 ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1698&aid=2872&group_id=426