You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@zookeeper.apache.org by "Gábor Lipták (JIRA)" <ji...@apache.org> on 2015/07/03 09:56:04 UTC

[jira] [Created] (ZOOKEEPER-2231) ServerSocket opened by ZooKeeperServer cannot use SO_REUSEADDR under Linux

Gábor Lipták created ZOOKEEPER-2231:
---------------------------------------

             Summary: ServerSocket opened by ZooKeeperServer cannot use SO_REUSEADDR under Linux
                 Key: ZOOKEEPER-2231
                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-2231
             Project: ZooKeeper
          Issue Type: Bug
          Components: server
    Affects Versions: 3.4.6
         Environment: $ uname -a
Linux 3.19.0-20-generic #20-Ubuntu SMP Fri May 29 10:10:47 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)

            Reporter: Gábor Lipták


I think reporting [this stackoverflow question|http://stackoverflow.com/q/31163513/337621] to the ZooKeeper team is important.

org.apache.zookeeper.server.NIOServerCnxnFactory.configure(InetSocketAddress, int) has the following code:
{code:java}
@Override
public void configure(InetSocketAddress addr, int maxcc) throws IOException {
    configureSaslLogin();

    thread = new Thread(this, "NIOServerCxn.Factory:" + addr);
    thread.setDaemon(true);
    maxClientCnxns = maxcc;
    this.ss = ServerSocketChannel.open();
    ss.socket().setReuseAddress(true);
    LOG.info("binding to port " + addr);
    ss.socket().bind(addr);
    ss.configureBlocking(false);
    ss.register(selector, SelectionKey.OP_ACCEPT);
}
{code}

So the intention is to use SO_REUSEADDR. This does not work under linux (at least with the java version I use). The reason is that sun.nio.ch.ServerSocketChannelImpl.setOption(SocketOption<T>, T) used by ZooKeeper has this code:

{code:java}
public <T> ServerSocketChannel setOption(SocketOption<T> paramSocketOption, T paramT) throws IOException
{
    if (paramSocketOption == null)
        throw new NullPointerException();
    if (!(supportedOptions().contains(paramSocketOption)))
        throw new UnsupportedOperationException("'" + paramSocketOption + "' not supported");
    synchronized (this.stateLock) {
        if (!(isOpen()))
            throw new ClosedChannelException();
        if ((paramSocketOption == StandardSocketOptions.SO_REUSEADDR) && (Net.useExclusiveBind()))
        {
            this.isReuseAddress = ((Boolean)paramT).booleanValue();
        }
        else {
            Net.setSocketOption(this.fd, Net.UNSPEC, paramSocketOption, paramT);
        }
        return this;
    }
}
{code}

"Net.useExclusiveBind()" seems to give back always false under linux no matter what value is set for [sun.net.useExclusiveBind|http://www.oracle.com/technetwork/java/javase/7u25-relnotes-1955741.html#napi-win] environment entry.

If someone wants to stop and start an embedded ZooKeeper server, it can result in BindExceptions. If there would be some workaround under Linux, it would be really good.

Also under windows the sun.net.useExclusiveBind env entry seems to be important to have the SO_REUSEADDR option. Maybe it would worth to document this network setting.

I have a [test code|http://pastebin.com/Hhyfiz3Y] which can reproduce the BindException under Linux.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)