0

Does anyone encountered the issue with NanoHttpd leaking threads?

The thing is the library creates a new thread for each incoming request and while I see response for those requests the internal thread that was running requests processing is never finished. That leads to that it has eventually several hundreds of leaked threads and app crash.

My code is pretty much basic and straightforward. I just sublclass NanoHTTPD and override serve() method.

I've debugged the lib itself and it loops in the following code forever in NanoHTTPD class:

while (!finalAccept.isClosed()) {        
    session.execute();
}

Any suggestions?

Update: Turned out that this is and edge case that is connected to the client app that makes requests to my app where http server is launched. When I make requests from Chrome or with curl it doesn't leak any threads.

Roman Minenok
  • 9,328
  • 4
  • 26
  • 26
  • I think your serve() method implementation is needed to answer this question. – Pierre Rust Feb 21 '14 at 14:11
  • @PierreRust the method is very simple. Turned out that this is and edge case that is connected to the client app that makes requests to my app. When I make requests from Chrome or curl it doesn't leak threads. – Roman Minenok Feb 21 '14 at 14:49
  • I thought about that, your client is probably not closing the connection when it has finished with it. Nanohttp would then loop trying to read on the socket, it does not seems to have an hard timeout mechanism. – Pierre Rust Feb 21 '14 at 15:15
  • @PierreRust yes, something like that, investigating. List this comment as separate answer and I'll accept it. BTW Could you also specify at least in some generic way where I can read about client's responsibility to close a connection? – Roman Minenok Feb 21 '14 at 15:39

1 Answers1

1

I believe this leak is caused by your client not closing the socket. NanoHttpd uses a timeout of 5s on read and only stops the serving thread when the socket has been closed on client side :

Line 190 :

} catch (Exception e) {
    // When the socket is closed by the client, we throw our own SocketException
    // to break the "keep alive" loop above.
    if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage()))) {
        e.printStackTrace();
    }

}

Line 863 :

if (read == -1) {
    // socket was been closed
    safeClose(inputStream);
    safeClose(outputStream);
    throw new SocketException("NanoHttpd Shutdown");
}

I would suggest checking if your client correctly closes the connection and maybe write your own AsyncRunner implementation instead of the DefaultAsyncRunner provided by NanoHttpd, in order to limit the number of threads. You could also implement, on top of that, a mechanism to stop threads serving for more than x sec (30s would be a good start imo).

Pierre Rust
  • 2,474
  • 18
  • 15