Under load I'm sometime getting the following NPE in Undertow:
2016-04-23 21:31:52,647 ERROR [io.undertow.request] (default task-96) UT005071: Undertow request failed HttpServerExchange{ POST /XXX request {Accept=[*/*], X-Requested-With=[XMLHttpRequest], Accept-Language=[en-us], Cache-Control=[no-cache], User-Agent=[Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko], Connection=[Keep-Alive], X-Forwarded-Proto=[https], X-Forwarded-Port=[443], X-Forwarded-For=[XXX], Content-Type=[application/x-www-form-urlencoded; charset=UTF-8], Content-Length=[2014], Cookie=[JSESSIONID=Z6_twcAUmbh5EbU_cVzOr3Wj2LPj77tHJbJSs_0Z.XXX], Referer=[XXX], Host=[XXX]} response {Connection=[close], Content-Length=[0], Date=[Sun, 24 Apr 2016 01:31:52 GMT]}}: java.lang.NullPointerException at io.undertow.server.Connectors.terminateResponse(Connectors.java:99) at io.undertow.server.protocol.http.ServerFixedLengthStreamSinkConduit.channelFinished(ServerFixedLengthStreamSinkConduit.java:55) at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.exitFlush(AbstractFixedLengthStreamSinkConduit.java:309) at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.flush(AbstractFixedLengthStreamSinkConduit.java:234) at org.xnio.conduits.ConduitStreamSinkChannel.flush(ConduitStreamSinkChannel.java:162) at io.undertow.channels.DetachableStreamSinkChannel.flush(DetachableStreamSinkChannel.java:119) at org.xnio.channels.Channels.flushBlocking(Channels.java:63) at io.undertow.servlet.spec.ServletOutputStreamImpl.close(ServletOutputStreamImpl.java:609) at io.undertow.servlet.spec.HttpServletResponseImpl.closeStreamAndWriter(HttpServletResponseImpl.java:478) at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:561) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:332) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:264) at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:175) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:792) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
When looking at the code:
https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/conduits/AbstractFixedLengthStreamSinkConduit.java
public boolean flush() throws IOException { long val = state; if (anyAreSet(val, FLAG_CLOSE_COMPLETE)) { return true; } boolean flushed = false; try { return flushed = next.flush(); } catch (IOException e) { broken = true; throw e; } finally { exitFlush(val, flushed); } } private void exitFlush(long oldVal, boolean flushed) { long newVal = oldVal; boolean callFinish = false; if ((anyAreSet(oldVal, FLAG_CLOSE_REQUESTED) || (newVal & MASK_COUNT) == 0L) && flushed) { newVal |= FLAG_CLOSE_COMPLETE; if (!anyAreSet(oldVal, FLAG_FINISHED_CALLED) && (newVal & MASK_COUNT) == 0L) { newVal |= FLAG_FINISHED_CALLED; callFinish = true; } state = newVal; if (callFinish) { channelFinished(); } } }
@Override
protected void channelFinished() {
Connectors.terminateResponse(exchange);
}
public static void terminateResponse(final HttpServerExchange exchange) { exchange.terminateResponse(); }
I fear that maybe there's a way that exchange is null for some reason. Also, with the try/catch/finally pattern used, could it be possible that we loose some stack trace information if something goes wrong in the exitFlush method?
Like I mentioned previously this only happen sometime and while under load and I haven't found yet a way to reproduce the issue. Is there anything I could do to help/investigate further?
Thanks,
- clones
-
UNDERTOW-707 NPE in io.undertow.server.Connectors.terminateResponse
- Resolved