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)