Bug 31557 - Sockets with ReuseAddress does not seem to be working as expected
Summary: Sockets with ReuseAddress does not seem to be working as expected
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: io-layer (show other bugs)
Version: 4.0.0
Hardware: Other Linux
: Normal normal
Target Milestone: 4.2 (C6)
Assignee: marcos.henrich
URL:
Depends on:
Blocks:
 
Reported: 2015-07-01 17:21 UTC by Stefan
Modified: 2015-10-06 12:14 UTC (History)
5 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

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));
    socket1.Listen(1);

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


Should I expect this to work under Mono/Linux?



Thanks
Stefan
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);
		}
	}
#endif


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?




Thanks
Stefan
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.



Thanks
Stefan
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:
https://github.com/mono/mono/pull/2047
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!


Thanks
Stefan
Comment 6 marcos.henrich 2015-09-21 09:17:19 UTC
Fixed in mono master 07bae963aea19bb6c293ad3176c3f707ac94d2a2.
https://github.com/mono/mono/commit/07bae963aea19bb6c293ad3176c3f707ac94d2a2

Fixed in mono mono-4.2.0-branch 4a18c575ac105b920ec7fb37b24ffe74ad9b3bd7.
https://github.com/mono/mono/commit/4a18c575ac105b920ec7fb37b24ffe74ad9b3bd7

Note You need to log in before you can comment on or make changes to this bug.