Bug 31557

Summary: Sockets with ReuseAddress does not seem to be working as expected
Product: [Mono] Runtime Reporter: Stefan <stefan.sedich>
Component: io-layerAssignee: marcos.henrich
Severity: normal CC: kumpera, mono-bugs+mono, mono-bugs+runtime, peter.collins, stefan.sedich
Priority: Normal    
Version: 4.0.0   
Target Milestone: 4.2 (C6)   
Hardware: Other   
OS: Linux   
Tags: Is this bug a regression?: ---
Last known good build:

Description Stefan 2015-07-01 17:21:39 UTC
The following example seems to have issues running under Mono (nightly 4.3.0, ubuntu 14.04), on windows as expected the second socket is bound and starts listening, but under mono this fails with an exception telling me that the "Address is already in use":

    var socket1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket1.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket1.Bind(new IPEndPoint(IPAddress.Loopback, 1234));

    var socket2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket2.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket2.Bind(new IPEndPoint(IPAddress.Loopback, 1234));

Should I expect this to work under Mono/Linux?

Comment 1 Stefan 2015-07-07 23:15:44 UTC
Just some more findings on this after looking into the sockets.c implementation, I can see the code that sets SO_REUSEPORT which is executed under Ubuntu, starting at line#729:

#if defined (SO_REUSEPORT)
	/* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
	if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
		int type;
		socklen_t type_len = sizeof (type);

		if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
			if (type == SOCK_DGRAM)
				setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);

The bit that interests me is starting at line#736:

if (type == SOCK_DGRAM)
				setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);

Unless I am wrong will that only apply to UDP sockets? if I remove this check or change it to (type == SOCK_STREAM) it then works as expected for me with the example above, is there a reason that this check is there that I do not understand?

Comment 2 Rodrigo Kumpera 2015-08-16 03:16:44 UTC
Hey Marcos,

Can you take a look at this one?
Comment 3 Stefan 2015-09-10 18:18:32 UTC
Thanks Rodrigo, do you know if anyone got a chance to verify what I was seeing. Be great if I can have some clarification either way.

Comment 4 marcos.henrich 2015-09-11 12:46:42 UTC
Hi Stefan,

Thank you for the detailed bug report and for finding a fix for the issue.

Here is the pull request fixing the issue:
Comment 5 Stefan 2015-09-11 19:06:47 UTC
Thanks Marcos!

That was the exact fix I had in mind! I guess I just wasn't sure if there was a historical reason for it being like this that I did not know about.

Appreciate you looking into this done and fixing it up!

Comment 6 marcos.henrich 2015-09-21 09:17:19 UTC
Fixed in mono master 07bae963aea19bb6c293ad3176c3f707ac94d2a2.

Fixed in mono mono-4.2.0-branch 4a18c575ac105b920ec7fb37b24ffe74ad9b3bd7.