Uploaded image for project: 'Undertow'
  1. Undertow
  2. UNDERTOW-1595

NullPointerException can happen on a range request for a static content

XMLWordPrintable

    • Hide

      1. Create enough size of static content which is larger than the buffer size (16 KiB = 16384 Bytes by default)

      base64 /dev/urandom | head -c 1024000 > $JBOSS_HOME/welcome-content/test.txt
      

      2. Start JBoss EAP with the following byteman rule which just sleep before writing a response.
      This rule can make a client easy to similate an abrupt connection close.

      RULE sleep_at_AsyncSenderImpl_send
      CLASS io.undertow.io.AsyncSenderImpl
      METHOD send
      AT ENTRY
      IF TRUE
      DO
          # traceStack("------- io.undertow.io.AsyncSenderImpl#send() -------\n");
          traceln("------- sleeping... -------");
          delay(10000L);
          traceln("------- sleep done! -------");
      ENDRULE
      

      3. Execute the following curl command to send a range request, then stop with "Ctrl-C" while the server sleep by the byteman rule

      curl -v -r 0-16384 http://localhost:8080/test.txt
      

      Then, you will see NullPointerException in the server.log at the end of request processing.

      Note:

      • The range size should be larger than the buffer size (16 KiB = 16384 Bytes by default).
      • As IOException need to happen during sending the last part of the range response, the range size should be between "0-16384" ~ "0-32767" to reproduce the issue by stopping the curl command during the 1st sleep.
      Show
      1. Create enough size of static content which is larger than the buffer size (16 KiB = 16384 Bytes by default) base64 /dev/urandom | head -c 1024000 > $JBOSS_HOME/welcome-content/test.txt 2. Start JBoss EAP with the following byteman rule which just sleep before writing a response. This rule can make a client easy to similate an abrupt connection close. RULE sleep_at_AsyncSenderImpl_send CLASS io.undertow.io.AsyncSenderImpl METHOD send AT ENTRY IF TRUE DO # traceStack( "------- io.undertow.io.AsyncSenderImpl#send() -------\n" ); traceln( "------- sleeping... -------" ); delay(10000L); traceln( "------- sleep done! -------" ); ENDRULE 3. Execute the following curl command to send a range request, then stop with "Ctrl-C" while the server sleep by the byteman rule curl -v -r 0-16384 http: //localhost:8080/test.txt Then, you will see NullPointerException in the server.log at the end of request processing. Note: The range size should be larger than the buffer size (16 KiB = 16384 Bytes by default). As IOException need to happen during sending the last part of the range response, the range size should be between "0-16384" ~ "0-32767" to reproduce the issue by stopping the curl command during the 1st sleep.

      NullPointerException can happen on the range request for a static content. This happens if the following conditions are met:

      • A size of Range request is larger than the buffer size (16 KiB = 16384 Bytes by default)
      • IOException (DEBUG level logging on io.undertow.request.io) occurs during sending the last part of the range response
        (for example, a client browser close the connection or a front-end proxy closed the connection due to timeout)
      ERROR [io.undertow.request] (default task-1) UT005071: Undertow request failed HttpServerExchange{ GET /test.txt}: java.lang.NullPointerException
      	at io.undertow.server.handlers.resource.PathResource$1ServerTask.run(PathResource.java:156)
      	at io.undertow.server.handlers.resource.PathResource$1ServerTask.onComplete(PathResource.java:200)
      	at io.undertow.io.AsyncSenderImpl.invokeOnComplete(AsyncSenderImpl.java:413)
      	at io.undertow.io.AsyncSenderImpl.send(AsyncSenderImpl.java:173)
      	at io.undertow.server.handlers.resource.PathResource$1ServerTask.run(PathResource.java:187)
      	at io.undertow.server.handlers.resource.PathResource.serveImpl(PathResource.java:256)
      	at io.undertow.server.handlers.resource.PathResource.serveRange(PathResource.java:118)
      	at io.undertow.server.handlers.resource.ResourceHandler$1.handleRequest(ResourceHandler.java:335)
      	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
      	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
      	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
      	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
      	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
      	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1349)
      	at java.lang.Thread.run(Thread.java:748)
      

      It seems this NPE is harmless because the connection is already closed and no bad side effects happen to the response anymore. However, of course, it's better to avoid NPE.

              flaviarnn Flavia Rainone
              rhn-support-mmiura Masafumi Miura
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: