NPE in Servlet30AsyncProvider

22 views
Skip to first unread message

Andreas Joseph Krogh

unread,
Jan 11, 2017, 5:08:44 AM1/11/17
to lif...@googlegroups.com
Hi all.
 
I'm seeing this from time to time (Using tomcat-8.0.12) and Lift-3.0.1 with scala-2.12.1:
 
2017-01-11 09:54:17,980 ERROR [liftExecutor-1-thread-16] - [] []  ActorLogger                    - Actor threw an exception
java.lang.NullPointerException
       at sun.reflect.GeneratedMethodAccessor158.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       at java.lang.reflect.Method.invoke(Method.java:497)
       at net.liftweb.http.provider.servlet.containers.Servlet30AsyncProvider.resume(Servlet30AsyncProvider.scala:115)



It seems this is caused because getResponse is null:
val httpRes = getResponse.invoke(asyncCtx).asInstanceOf[javax.servlet.http.HttpServletResponse]
 
Which it only can be if the catch-clause is reached:
 
  try {
    val cc = Class.forName("javax.servlet.ServletRequest")
    val asyncClass = Class.forName("javax.servlet.AsyncContext")
    val startAsync = cc.getMethod("startAsync")
    val getResponse = asyncClass.getMethod("getResponse")
    val complete = asyncClass.getMethod("complete")
    val isSupported = cc.getMethod("isAsyncSupported")
    (true, cc, asyncClass, startAsync, getResponse, complete, isSupported)
  } catch {
    case e: Exception =>
      (false, 
       null, 
       null, 
       null, 
       null, 
       null,
       null)
  }
}
 
I wonder, is't Servlet30AsyncProvider.resume protected by suspendResumeSupport_? ?
 
This only happens once in 1000 runs (of course), has any one seen this?
 
--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963

Diego Medina

unread,
Jan 11, 2017, 5:50:19 AM1/11/17
to Lift
I have seen it, here is a recent post about it


but since we upgraded to the latest jetty, it hasn't come up on our logs

what do you think of the idea of making the try catch I talked about on that thread cover 

getResponse

too?

Thanks

Diego


--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Diego Medina
Lift/Scala Consultant
di...@fmpwizard.com
https://blog.fmpwizard.com/

Andreas Joseph Krogh

unread,
Jan 11, 2017, 7:24:19 AM1/11/17
to lif...@googlegroups.com
På onsdag 11. januar 2017 kl. 11:50:12, skrev Diego Medina <di...@fmpwizard.com>:
I have seen it, here is a recent post about it
 
 
but since we upgraded to the latest jetty, it hasn't come up on our logs
 
what do you think of the idea of making the try catch I talked about on that thread cover 
 
getResponse
 
too?
 
No, I think moving try to cover line 115 is the wrong approach. IMO this code should never be executed if getResponse is null. So there must be some logic-breakage when suspendResumeSupport_? is true and getResponse == null, which should be fixed. Servlet30AsyncProvider.resume should never get called when in this state.
It might be worth adding more logging(TRACE) to Servlet30AsyncProvider.suspend/resume to understand what really happens?

Antonio Salazar Cardozo

unread,
Jan 11, 2017, 8:56:01 AM1/11/17
to Lift
Are you sure it's not asyncCtx that's `null`? I think that's where the stack
trace you're showing would come up (otherwise `.invoke` would throw the
NPE directly in the method).

Having a null `asyncCtx` in `resume` would imply that we never got an async
context from the container to begin with. The code definitely seems to be written
with the assumption that such a context will always be provided, but perhaps
there are bugs in the container that mean that's not always true. Or, perhaps
there is intentional behavior in the container that means it's not always true.
If there's intentional behavior and it's up to spec, then we need to adjust how
we interact with these.

Btw, you can add logging inside your own app by creating an async provider
and adding it via LiftRules.addSyncProvider. You'll probably need to create
it inside the net.liftweb.http.provider.servlet package (in your codebase), though,
as I seem to recall you need access to a couple of package-private functions to
make it work correctly. I did this a coupe of days ago hunting down a different bug.
Thanks,
Antonio
Reply all
Reply to author
Forward
0 new messages