Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-vaadin initiated session timeout with MPR triggers IllegalStateException : Session Already Invalidated #65

Closed
petrixh opened this issue Feb 25, 2020 · 0 comments

Comments

@petrixh
Copy link

petrixh commented Feb 25, 2020

In a project running:
Vaadin 14.0.10, Vaadin 8.9.1
MPR 2.0.0
SpringSecurity
Tomcat

Original ticket in Vaadin internal repo: https://github.com/vaadin/multiplatform-runtime-internal/issues/340

When the user's session times out or is killed by 3 missed heartbeats, or by spring security's logout URL we see an exception in the logs about the session already being invalidated.

There's quite a bit of setup before this can be tried out as it needs many moving parts but based on the stack traces and some investigation it seems that the v8 VaadinService tries to access the session during the fireSessionDestroy part, which will throw if the session is already invalidated.

There's basically a couple of different paths were we've observed this:

For sanity sake, we set:
vaadin.heartbeatInterval=15
vaadin.closeIdleSessions=true
server.servlet.session.timeout=60s

Login to the application and land on a view that mixes v14 and v8 components (i.e. both runtimes are enabled)
close the browser
Use another browser (like Safari if you used Chrome earlier) to generate some small traffic on the server
After about 45-60 seconds you'll see a stacktrace:

2019-10-24 15:32:10.322  WARN 59167 --- [alina-utility-1] o.apache.catalina.core.StandardContext   : Exception processing manager [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] background process
java.lang.IllegalStateException: getAttribute: Session already invalidated
at org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1145)
at org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:103)
at com.vaadin.server.WrappedHttpSession.getAttribute(WrappedHttpSession.java:54)
at com.vaadin.mpr.core.MprServletService.getFlowSession(MprServletService.java:183)
at com.vaadin.mpr.core.MprServletService.accessSession(MprServletService.java:158)
at com.vaadin.server.VaadinSession.access(VaadinSession.java:1417)
at com.vaadin.server.VaadinService.fireSessionDestroy(VaadinService.java:529)
at com.vaadin.server.VaadinSession.valueUnbound(VaadinSession.java:313)
at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1784)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:856)
at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:659)
at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:573)
at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:558)
at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5539)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Tracing the stacktrace down, you'll see that com.vaadin.server.VaadinService#fireSessionDestroy() will call ".access()" on the session which tries to get the Flow session (through MprVaadinService) which eventually ends up in "StandardSession.getAttribute()" which is not allowed if the session "is not valid"...

Second case:

Configure SpringSecurity to have a "logout url"
open a browser
logon and land on a page that mixes v14 and v8
change the URL to the SpringSecurity logout url
You'll notice a stacktrace like:

2019-10-24 16:22:50.641 ERROR 68576 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[springServlet] : Servlet.service() for servlet [springServlet] in context with path [] threw exception

java.lang.IllegalStateException: getAttribute: Session already invalidated
at org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1145)
at org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:103)
at com.vaadin.server.WrappedHttpSession.getAttribute(WrappedHttpSession.java:54)
at com.vaadin.mpr.core.MprServletService.getFlowSession(MprServletService.java:183)
at com.vaadin.mpr.core.MprServletService.accessSession(MprServletService.java:158)
at com.vaadin.server.VaadinSession.access(VaadinSession.java:1417)
at com.vaadin.server.VaadinService.fireSessionDestroy(VaadinService.java:529)
at com.vaadin.server.VaadinSession.valueUnbound(VaadinSession.java:313)
at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1784)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:856)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:743)
at org.apache.catalina.session.StandardSession.invalidate(StandardSession.java:1229)
at org.apache.catalina.session.StandardSessionFacade.invalidate(StandardSessionFacade.java:171)
at org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler.logout(SecurityContextLogoutHandler.java:66)
at org.springframework.security.web.authentication.logout.CompositeLogoutHandler.logout(CompositeLogoutHandler.java:54)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:109)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Tracing this one back, it is apparent that in this case Spring is invalidating the session, which causes the same kind of exception as the Tomcat session timeout case above.

A third case:

logon to the application and land on a v14 v8 mixed view
leave the browser idling and let the "closeIdleSesssions" do its thing
observe that you again have a stacktrace, which one depends on who/what triggered it
a) the next heartbeat
b) tomcats internal processing (this one is hard to reproduce with a short heartbeat interval but essentially the same as closing the browser)

@pleku pleku added this to Needs triage in OLD Vaadin Flow bugs & maintenance (Vaadin 10+) via automation Feb 27, 2020
@pleku pleku added BFP bug Something isn't working labels Feb 28, 2020
@pleku pleku moved this from Needs triage to P1 - High priority in OLD Vaadin Flow bugs & maintenance (Vaadin 10+) Feb 28, 2020
@caalador caalador self-assigned this Mar 4, 2020
@caalador caalador moved this from Ready To Go to In progress in OLD Vaadin Flow ongoing work (Vaadin 10+) Mar 4, 2020
@caalador caalador closed this as completed Mar 9, 2020
OLD Vaadin Flow ongoing work (Vaadin 10+) automation moved this from In progress to Done - pending release Mar 9, 2020
OLD Vaadin Flow bugs & maintenance (Vaadin 10+) automation moved this from P1 - High priority to Closed - pending release Mar 9, 2020
@denis-anisimov denis-anisimov added this to the 2.0.3 milestone Mar 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants