Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Feb 2006 10:11:38 -0500
From:      Kurt Miller <kurt@intricatesoftware.com>
To:        freebsd-java@freebsd.org
Cc:        Nate Williams <nate@yogotech.com>, "Arne H. Juul" <arnej@pvv.ntnu.no>
Subject:   Re: SO_REUSEADDR should not also mean SO_REUSEPORT
Message-ID:  <200602211011.39387.kurt@intricatesoftware.com>
In-Reply-To: <Pine.LNX.4.62.0602182107440.31913@decibel.pvv.ntnu.no>
References:  <43F4F22F.1060402@europe.yahoo-inc.com> <17399.20883.741021.688682@caddis.yogotech.com> <Pine.LNX.4.62.0602182107440.31913@decibel.pvv.ntnu.no>

next in thread | previous in thread | raw e-mail | index | archive | help
On Saturday 18 February 2006 3:45 pm, Arne H. Juul wrote:
> On Sat, 18 Feb 2006, Nate Williams wrote:
> >> Ok, thanks. I got that impression from reading some posts I found
> >> while googling. There was one in particular for NetBSD that
> >> discussed it in detail. Check out the Apr 2 portion of this
> >> http://www.tinyurl.com/b46gq by Jan Schaumann. Also this
> >> one http://tinyurl.com/9sa6a. From these posts it appears
> >> that SO_REUSEPORT is needed in some cases to be compatible
> >> with linux.
> >
> >> From the early days....
> >
> >  - In the Multicast constructor, the low level routine sets the
> >    SO_REUSEADDR option by using JSO_REUSEADDR which corresponds to a call
> >    to setsockopt(..SO_REUSEADDR).  To make multicast sockets work in *all*
> >    cases on FreeBSD, we should also set SO_REUSEPORT, else in many cases
> >    the multicast bind will fail.
> 
> I won't claim to know what's the best behaviour with multicast, but the 
> problem is that SO_REUSEPORT is always used when SO_REUSEADDR was 
> requested, meaning that:
> 
> > SO_REUSEPORT allows completely duplicate bindings by multiple
> > processes if they all set SO_REUSEPORT before binding the port.
> 
> so you can have two very different java servers listening on the same 
> port, for example.  Or the same java server started twice won't notice any 
> problem because the second instance will bind its server port fine, while 
> on all other OSes this would give a sensible error message.  And so on. 
> This is bad.
> 
> The reason I found this problem in the first place was from a Java program 
> that worked well on Linux, not at all on FreeBSD, and after much tracing 
> we deduced that something was enabling SO_REUSEPORT on FreeBSD, after 
> which finding the bad code was a simple matter of "grep", only leaving the 
> question of why it was there in the first place.
> 
> If anybody figures out what's best practice for supporting multicast 
> applications, ask the BSD kernel people to change the kernel behaviour to 
> match best practice, make it possible to control SO_REUSEPORT from the 
> MulticastSocket class, or find some other solution that doesn't make 
> *other* types of java application suffer.

Thanks for the explanation and also to Nate for the Multicast
history. I've looked into this a bit more over the weekend and
found that the network stack promotes SO_REUSEADDR to include
SO_REUSEPORT for multicast addresses, so I believe that case is
covered already. I ran the network jck's on the 1.5 jvm with your
patch and found that SO_REUSEPORT is still needed to pass the jck's
but for datagram sockets only.

Could you try this patch and test it with the program you referred
to above?

--- ../../j2se/src/solaris/native/java/net/net_util_md.c.orig	Tue Feb 21 09:56:11 2006
+++ ../../j2se/src/solaris/native/java/net/net_util_md.c	Tue Feb 21 10:06:31 2006
@@ -1022,11 +1022,20 @@
     }
 
     /*
-     * If SO_REUSEADDR option requested, unconditionally set SO_REUSEPORT.
+     * If SO_REUSEADDR option requested for SOCK_DGRAM, set SO_REUSEPORT also.
      */
     if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
-	addopt = SO_REUSEPORT;
-	setsockopt(fd, level, addopt, arg, len);
+        int sotype, arglen;
+
+        arglen = sizeof(sotype);
+        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
+            return -1;
+        }
+
+        if (sotype == SOCK_DGRAM) {
+            addopt = SO_REUSEPORT;
+            setsockopt(fd, level, addopt, arg, len);
+        }
     }
 
     /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200602211011.39387.kurt>