Results 1 to 9 of 9

Thread: [Bug] SenchaCmd doesn't use SO_REUSEADDR correctly

  1. #1
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default [Bug] SenchaCmd doesn't use SO_REUSEADDR correctly

    When you exit a "sencha app watch", the operating system sometimes leaves the port in a state which is called TIME_WAIT (at least on Linux and OS X) and that state is maintained even after the sencha process has been closed. On Linux it stays in this state for 60 seconds after the process has been closed.

    So far that is totally normal. The problem is that SenchaCmd doesn't set the "SO_REUSEADDR" flag correctly causing it to not be able to pick up the port again while it is in TIME_WAIT state.

    And that is causing issues for me because I have a proxy set up that allows accessing the sencha app (in app watch mode) and other services on routes like "localhost/ext" and "localhost/node" so that I don't run into CORS issues etc.

    Since the source code for SenchaCmd doesn't appear to be public, I had to decompile the sencha.jar to find the cause. Here is the relevant reconstructed code:

    decompiled_sencha.jar/com/sencha/ant/WebServerTask.java:
    Code:
    if (this._port > 0 && !NetworkUtil.isPortAvailable(this._port)) {
        WebServerTask._logger.warn("Port {} already in use.  Using dynamic port instead.", (Object)this._port);
        this._port = 0;
    }
    decompiled_sencha.jar/com/sencha/util/NetworkUtil.java: isPortAvailable:
    Code:
    public static synchronized boolean isPortAvailable(final int port) {
        return _isPortAvailable(port, "127.0.0.1");
    }
    decompiled_sencha.jar/com/sencha/util/NetworkUtil.java: _isPortAvailable:
    Code:
    private static boolean _isPortAvailable(final int port, final String address) {
        return _socketChannelPortAvailable(port, address) && _serverSocketPortAvailable(port, address);
    }
    decompiled_sencha.jar/com/sencha/util/NetworkUtil.java: _serverSocketPortAvailable:
    Code:
    private static boolean _serverSocketPortAvailable(final int p, final String address) {
        ServerSocket srv = null;
        try {
            srv = new ServerSocket();
            srv.setReuseAddress(false);
            if (!StringUtil.isNullOrEmpty(address)) {
                srv.bind(new InetSocketAddress(address, p));
            }
            else {
                srv.bind(new InetSocketAddress(p));
            }
            return true;
        }
        catch (Exception ex2) {
            return false;
        }
        finally {
            if (srv != null) {
                try {
                    srv.close();
                }
                catch (Exception ex) {
                    throw BasicException.raise(ex);
                }
            }
        }
    }
    decompiled_sencha.jar/com/sencha/util/NetworkUtil.java: _socketChannelPortAvailable with 2 parameters:
    Code:
    private static boolean _socketChannelPortAvailable(final int p, final String address) {
        return _socketChannelPortAvailable(p, address, true);
    }
    decompiled_sencha.jar/com/sencha/util/NetworkUtil.java: _socketChannelPortAvailable with 3 parameters:
    Code:
    private static boolean _socketChannelPortAvailable(final int p, final String address, final boolean reuseAddr) {
        ServerSocketChannel srv = null;
        try {
            srv = ServerSocketChannel.open();
            if (!reuseAddr) {
                srv.setOption(StandardSocketOptions.SO_REUSEADDR, false);
            }
            if (!StringUtil.isNullOrEmpty(address)) {
                srv.bind(new InetSocketAddress(address, p));
            }
            else {
                srv.bind(new InetSocketAddress(p));
            }
            return true;
        }
        catch (Exception ex) {
            return false;
        }
        finally {
            if (srv != null) {
                try {
                    srv.close();
                }
                catch (Exception ex2) {}
            }
        }
    }
    As you can see in _socketChannelPortAvailable (the one that has the third "reuseAddr" parameter) in decompiled_sencha.jar/com/sencha/util/NetworkUtil.java there is this code:
    Code:
    if (!reuseAddr) {
         srv.setOption(StandardSocketOptions.SO_REUSEADDR, false);
    }
    From what I understand SO_REUSEADDR is already false by default making this code kind of redundant. But when reuseAddr is true, SO_REUSEADDR will not be set to true!

    The fix would be to remove the if statement and instead simply pass the reuseAddr argument:

    Code:
    srv.setOption(StandardSocketOptions.SO_REUSEADDR, reuseAddr);

    Please tell me if and when you will fix this. Thank you.

  2. #2
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    @SenchaCmdTeam Can you please say something about this?

  3. #3
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    Is SenchaCmd dead? The releases page looks pretty fake. You are just releasing the same versions over and over again:


  4. #4
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    I'm still waiting for a response.

  5. #5
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    @SenchaCmdTeam Can you please respond?

  6. #6
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    @SenchaCmdTeam Hello?

  7. #7
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    Are you still alive?

  8. #8
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    Still looking for a response.

  9. #9
    Sencha User
    Join Date
    Sep 2016
    Posts
    17

    Default

    Bump. Still looking for a response.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •