Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need ability to set Socket.setReuseAddress() in RubyTCPSocket.java #378

Closed
drbobbeaty opened this Issue Nov 8, 2012 · 1 comment

Comments

Projects
None yet
2 participants
@drbobbeaty
Copy link

drbobbeaty commented Nov 8, 2012

Set-Up

I'm working with the CouchRest Gem, and a massively multi-threaded, multi-process system where we are creating and closing sockets a lot. This gets us into trouble when the code hits the following lines in RubyTCPSocket.java:

try {
    // This is a bit convoluted because (1) SocketChannel.bind is only in jdk 7 and
    // (2) Socket.getChannel() seems to return null in some cases
    channel = SocketChannel.open();
    Socket socket = channel.socket();

    if (localHost != null) {
        socket.bind( new InetSocketAddress(InetAddress.getByName(localHost), localPort) );
    }

The problem is that the time from the closing of a Socket to the opening, and therefore calling of bind() on the same host/port combination is insufficient to have the OS release the socket.

Typically, you want to set SO_REUSEADDR to true and then you can very quickly reuse that same host/port address.

Proposed Solution

My ideal solution would be to have setReuseAddress() always called with true because the number of times you don't want this are few and far between. Another idea would be able to make a system default like: -Djruby.socket.reuse=true or something where we can set it to be tru for all sockets we create in that process.

try {
    // This is a bit convoluted because (1) SocketChannel.bind is only in jdk 7 and
    // (2) Socket.getChannel() seems to return null in some cases
    channel = SocketChannel.open();
    Socket socket = channel.socket();

    socket.setReuseAddress(true);
    if (localHost != null) {
        socket.bind( new InetSocketAddress(InetAddress.getByName(localHost), localPort) );
    }

The less than ideal, but very workable solution is to have options that allow this to be set before the bind() call. This is bad in that it means I have to make sure these options are exposed in every Ruby Gem that uses sockets, and that means a lot of changes for something that, for me, is really a global preference.

@headius

This comment has been minimized.

Copy link
Member

headius commented Aug 1, 2015

Ok, after three years I actually looked into this.

MRI does set SO_REUSEADDR by default, but only on INET_SERVER sockets (TCPServer). I'll make that change, but for other sockets where you want to reuse you'll need to set it (as in MRI).

@headius headius closed this in 4d7548c Aug 6, 2015

headius added a commit that referenced this issue Aug 6, 2015

@headius headius added this to the JRuby 9.0.1.0 milestone Aug 6, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.