diff --git a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs index f8c2f4cb750d6..fbc2bff995e01 100755 --- a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs @@ -9,8 +9,10 @@ // using System; +using System.Linq; using System.Collections; using System.Threading; +using System.Text.RegularExpressions; using System.Net; using System.Net.Sockets; using NUnit.Framework; @@ -3476,7 +3478,65 @@ public void UdpDoubleBind () ss.Close (); s.Close (); } - + + static bool supportsTcpReuse = false; + static bool supportsTcpReuseSet = false; + + static bool SupportsTcpReuse () + { + if (supportsTcpReuseSet) + return supportsTcpReuse; + + if (Path.DirectorySeparatorChar == '/') { + /* + * On UNIX OS + * Multiple threads listening to the same address and port are not possible + * before linux 3.9 kernel, where the socket option SO_REUSEPORT was introduced. + */ + Regex reg = new Regex(@"^#define\s*SO_REUSEPORT"); + foreach (string directory in Directory.GetDirectories ("/usr/include")) { + var f = Directory.GetFiles (directory, "socket.h").SingleOrDefault (); + if (f != null && File.ReadLines (f).Any (l => reg.Match (l).Success)) { + supportsTcpReuse = true; + break; + } + } + } else { + supportsTcpReuse = true; + } + + supportsTcpReuseSet = true; + + return supportsTcpReuse; + } + + // Test case for bug #31557 + [Test] + public void TcpDoubleBind () + { + using (Socket s = new Socket (AddressFamily.InterNetwork, + SocketType.Stream, ProtocolType.Tcp)) + using (Socket ss = new Socket (AddressFamily.InterNetwork, + SocketType.Stream, ProtocolType.Tcp)) { + s.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + + s.Bind (new IPEndPoint (IPAddress.Any, 12345)); + s.Listen(1); + + ss.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + + Exception ex = null; + try { + ss.Bind (new IPEndPoint (IPAddress.Any, 12345)); + ss.Listen(1); + } catch (SocketException e) { + ex = e; + } + + Assert.AreEqual (SupportsTcpReuse (), ex == null); + } + } + [Test] [Category ("NotOnMac")] public void ConnectedProperty () diff --git a/mono/io-layer/sockets.c b/mono/io-layer/sockets.c index 9121f86731c39..a6e7e349ab0a5 100644 --- a/mono/io-layer/sockets.c +++ b/mono/io-layer/sockets.c @@ -733,7 +733,7 @@ int _wapi_setsockopt(guint32 fd, int level, int optname, socklen_t type_len = sizeof (type); if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) { - if (type == SOCK_DGRAM) + if (type == SOCK_DGRAM || type == SOCK_STREAM) setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen); } }