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

Server.stop() and WebInfConfiguration.deconfigure() can throw a ClosedFileSystemException when restoring the original base resource #10134

Closed
mvysny opened this issue Jul 21, 2023 · 7 comments
Labels
Bug For general bugs on Jetty side

Comments

@mvysny
Copy link

mvysny commented Jul 21, 2023

Jetty version(s)
Jetty 12.0.0.beta3

Java version/vendor (use: java -version)
openjdk version "17.0.7" 2023-04-18

OS type/version
Ubuntu 23.04 x86-64

Description
Creating a resource via webAppContext.getResourceFactory().newResource(URL) causes that context to fail to stop/close, with the following exception:

2023-07-21 14:45:24.199 [main] INFO com.github.mvysny.vaadinboot.VaadinBoot - Main: Shutting down
2023-07-21 14:45:24.210 [main] INFO com.example.Bootstrap - Testapp shut down
2023-07-21 14:45:24.214 [main] ERROR com.github.mvysny.vaadinboot.VaadinBoot - stop() failed: java.nio.file.ClosedFileSystemException
java.nio.file.ClosedFileSystemException
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.ensureOpen(ZipFileSystem.java:1628)
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.checkAccess(ZipFileSystem.java:560)
	at jdk.zipfs/jdk.nio.zipfs.ZipPath.checkAccess(ZipPath.java:892)
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.checkAccess(ZipFileSystemProvider.java:172)
	at java.base/java.nio.file.Files.isAccessible(Files.java:2597)
	at java.base/java.nio.file.Files.isReadable(Files.java:2632)
	at org.eclipse.jetty.util.resource.PathResource.isReadable(PathResource.java:307)
	at org.eclipse.jetty.util.resource.Resources.isReadable(Resources.java:79)
	at org.eclipse.jetty.server.handler.ContextHandler.setBaseResource(ContextHandler.java:884)
	at org.eclipse.jetty.ee10.webapp.WebInfConfiguration.deconfigure(WebInfConfiguration.java:99)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.stopContext(WebAppContext.java:1222)
	at org.eclipse.jetty.ee10.servlet.ServletContextHandler.doStop(ServletContextHandler.java:1070)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:132)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.stop(ContainerLifeCycle.java:182)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStop(ContainerLifeCycle.java:205)
	at org.eclipse.jetty.server.Handler$Abstract.doStop(Handler.java:403)
	at org.eclipse.jetty.server.Server.doStop(Server.java:648)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:132)
	at com.github.mvysny.vaadinboot.VaadinBoot.stop(VaadinBoot.java:366)
	at com.github.mvysny.vaadinboot.VaadinBoot.run(VaadinBoot.java:260)
	at com.example.Main.main(Main.java:7)
2023-07-21 14:45:24.215 [Thread-19] INFO com.github.mvysny.vaadinboot.VaadinBoot - Shutdown hook called, shutting down
2023-07-21 14:45:24.216 [Thread-19] ERROR com.github.mvysny.vaadinboot.VaadinBoot - stop() failed: java.lang.NullPointerException: Cannot invoke "javax.naming.Context.destroySubcontext(String)" because "compCtx" is null
java.lang.NullPointerException: Cannot invoke "javax.naming.Context.destroySubcontext(String)" because "compCtx" is null
	at org.eclipse.jetty.ee10.plus.webapp.EnvConfiguration.deconfigure(EnvConfiguration.java:165)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.stopContext(WebAppContext.java:1222)
	at org.eclipse.jetty.ee10.servlet.ServletContextHandler.doStop(ServletContextHandler.java:1070)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:132)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.stop(ContainerLifeCycle.java:182)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStop(ContainerLifeCycle.java:205)
	at org.eclipse.jetty.server.Handler$Abstract.doStop(Handler.java:403)
	at org.eclipse.jetty.server.Server.doStop(Server.java:648)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:132)
	at com.github.mvysny.vaadinboot.VaadinBoot.stop(VaadinBoot.java:366)
	at com.github.mvysny.vaadinboot.VaadinBoot.lambda$run$0(VaadinBoot.java:246)
	at java.base/java.lang.Thread.run(Thread.java:833)

Workaround is to use ResourceFactory.root(), but this kind of factory never releases the resources until the JDK terminates, so this is not really a viable workaround.

How to reproduce?

  1. git clone https://github.com/mvysny/vaadin-boot
  2. cd vaadin-boot
  3. ./gradlew
  4. cd testapp/build/distributions/
  5. unzip testapp-12.0-SNAPSHOT.zip
  6. cd testapp/bin
  7. ./testapp
  8. When the app starts, press Enter to terminate the app

Thank you 👍

@joakime
Copy link
Contributor

joakime commented Jul 21, 2023

I don't think setting the Resource Base back to the original on deconfigure is needed anymore.

https://github.com/eclipse/jetty.project/blob/jetty-12.0.x/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebInfConfiguration.java#L97-L99

Another workaround (until I can test this) is to bind the ResourceFactory to the server lifecycle.

ResourceFactory resourceFactory = ResourceFactory.of(server); // bound to server lifecycle

@joakime
Copy link
Contributor

joakime commented Jul 24, 2023

@mvysny If I test your main branch from the https://github.com/mvysny/vaadin-boot repository using the staged 12.0.0 release.

See https://github.com/joakime/vaadin-boot/commits/fix/joakime-main

I get a clean build + test with no visible error.
Can you tell me how to replicate this issue using your repository?

@joakime
Copy link
Contributor

joakime commented Jul 24, 2023

OK, I was able to replicate.
Stand by, analyzing.

@joakime
Copy link
Contributor

joakime commented Jul 25, 2023

What I've learned so far.

This is an embedded Jetty scenario.
The Server is started from a set of JAR files, with a largish-classpath, set by the bin/testapp script.

It looks something like this ...

CLASSPATH=$APP_HOME/lib/testapp-12.0-SNAPSHOT.jar \ 
$APP_HOME/lib/vaadin-boot-12.0-SNAPSHOT.jar \ 
$APP_HOME/lib/jetty-slf4j-impl-12.0.0.jar \ 
$APP_HOME/lib/vaadin-core-24.1.3.jar \ 
$APP_HOME/lib/annotations-23.1.0.jar \ 
$APP_HOME/lib/jetty-ee10-websocket-jakarta-server-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-annotations-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-plus-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-webapp-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-websocket-servlet-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-servlet-12.0.0.jar \ 
$APP_HOME/lib/jetty-session-12.0.0.jar \ 
$APP_HOME/lib/jetty-xml-12.0.0.jar \ 
$APP_HOME/lib/vaadin-core-internal-24.1.3.jar \ 
$APP_HOME/lib/flow-lit-template-24.1.4.jar \ 
$APP_HOME/lib/flow-html-components-24.1.4.jar \ 
$APP_HOME/lib/flow-data-24.1.4.jar \ 
$APP_HOME/lib/flow-dnd-24.1.4.jar \ 
$APP_HOME/lib/vaadin-confirm-dialog-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-dev-24.1.3.jar \ 
$APP_HOME/lib/vaadin-dev-bundle-24.1.3.jar \ 
$APP_HOME/lib/vaadin-dev-server-24.1.4.jar \ 
$APP_HOME/lib/flow-server-24.1.4.jar \ 
$APP_HOME/lib/jetty-security-12.0.0.jar \ 
$APP_HOME/lib/jetty-websocket-core-server-12.0.0.jar \ 
$APP_HOME/lib/jetty-server-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-websocket-jakarta-client-12.0.0.jar \ 
$APP_HOME/lib/jetty-ee10-websocket-jakarta-common-12.0.0.jar \ 
$APP_HOME/lib/jetty-websocket-core-client-12.0.0.jar \ 
$APP_HOME/lib/jetty-client-12.0.0.jar \ 
$APP_HOME/lib/jetty-websocket-core-common-12.0.0.jar \ 
$APP_HOME/lib/jetty-http-12.0.0.jar \ 
$APP_HOME/lib/jetty-alpn-client-12.0.0.jar \ 
$APP_HOME/lib/jetty-io-12.0.0.jar \ 
$APP_HOME/lib/jetty-jndi-12.0.0.jar \ 
$APP_HOME/lib/jetty-util-12.0.0.jar \ 
$APP_HOME/lib/ph-css-7.0.0.jar \ 
$APP_HOME/lib/flow-push-24.1.4.jar \ 
$APP_HOME/lib/atmosphere-runtime-3.0.3.slf4jvaadin1.jar \ 
$APP_HOME/lib/license-checker-1.12.3.jar \ 
$APP_HOME/lib/directory-watcher-0.18.0.jar \ 
$APP_HOME/lib/ph-commons-11.0.1.jar \ 
$APP_HOME/lib/oshi-core-6.4.1.jar \ 
$APP_HOME/lib/slf4j-api-2.0.7.jar \ 
$APP_HOME/lib/open-8.5.0.jar \ 
$APP_HOME/lib/jakarta.websocket-api-2.1.1.jar \ 
$APP_HOME/lib/flow-commons-upload-24.1.4.jar \ 
$APP_HOME/lib/commons-io-2.11.0.jar \ 
$APP_HOME/lib/flow-client-24.1.4.jar \ 
$APP_HOME/lib/vaadin-lumo-theme-24.1.3.jar \ 
$APP_HOME/lib/vaadin-material-theme-24.1.3.jar \ 
$APP_HOME/lib/vaadin-accordion-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-avatar-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-upload-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-app-layout-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-button-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-checkbox-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-combo-box-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-custom-field-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-date-time-picker-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-date-picker-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-details-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-time-picker-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-select-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-side-nav-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-dialog-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-form-layout-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-field-highlighter-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-grid-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-icons-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-virtual-list-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-list-box-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-login-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-messages-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-ordered-layout-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-progress-bar-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-radio-button-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-notification-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-menu-bar-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-context-menu-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-renderer-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-split-layout-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-tabs-flow-24.1.3.jar \ 
$APP_HOME/lib/vaadin-text-field-flow-24.1.3.jar \ 
$APP_HOME/lib/jakarta.servlet-api-6.0.0.jar \ 
$APP_HOME/lib/jakarta.websocket-client-api-2.1.1.jar \ 
$APP_HOME/lib/jakarta.annotation-api-2.1.1.jar \ 
$APP_HOME/lib/asm-commons-9.5.jar \ 
$APP_HOME/lib/asm-tree-9.5.jar \ 
$APP_HOME/lib/asm-9.5.jar \ 
$APP_HOME/lib/throw-if-servlet3-1.0.2.jar \ 
$APP_HOME/lib/gwt-elemental-2.8.2.vaadin2.jar \ 
$APP_HOME/lib/jackson-annotations-2.15.2.jar \ 
$APP_HOME/lib/jackson-databind-2.15.2.jar \ 
$APP_HOME/lib/jackson-core-2.15.2.jar \ 
$APP_HOME/lib/jsoup-1.16.1.jar \ 
$APP_HOME/lib/gentyref-1.2.0.vaadin1.jar \ 
$APP_HOME/lib/commons-compress-1.23.0.jar \ 
$APP_HOME/lib/httpclient-4.5.14.jar \ 
$APP_HOME/lib/commons-codec-1.15.jar \ 
$APP_HOME/lib/vaadin-flow-components-base-24.1.3.jar \ 
$APP_HOME/lib/commons-lang3-3.12.0.jar \ 
$APP_HOME/lib/javaparser-core-3.25.3.jar \ 
$APP_HOME/lib/jakarta.transaction-api-2.0.1.jar \ 
$APP_HOME/lib/httpcore-4.4.16.jar \ 
$APP_HOME/lib/commons-logging-1.2.jar \ 
$APP_HOME/lib/nimbus-jose-jwt-9.31.jar \ 
$APP_HOME/lib/jcip-annotations-1.0.0.jar \ 
$APP_HOME/lib/jsr305-3.0.2.jar \ 
$APP_HOME/lib/jna-platform-5.13.0.jar \ 
$APP_HOME/lib/jna-5.13.0.jar \ 
$APP_HOME/resources/

exec java -classpath $CLASSPATH com.example.Main "$@"

Once started, a WebAppContext is initialized with a base resource of ...

jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/testapp-12.0-SNAPSHOT.jar!/webapp/

Upon startup the various WebApp Configurations run and the eventual base resource becomes a Combined Resource of ...

jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/testapp-12.0-SNAPSHOT.jar!/webapp/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/flow-client-24.1.4.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/flow-push-24.1.4.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-button-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-combo-box-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-grid-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-renderer-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-time-picker-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-select-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-text-field-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-flow-components-base-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-menu-bar-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/flow-dnd-24.1.4.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-virtual-list-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-messages-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-date-picker-flow-24.1.3.jar!/META-INF/resources/
jar:file:///home/joakim/tmp/vaadin-boot-testing/testapp/lib/vaadin-context-menu-flow-24.1.3.jar!/META-INF/resources/

Later, when the Server.stop() is called, the WebInfConfiguration.deconfigure() calls WebAppContext.setBaseResource(originalBaseResource).
The HEAD logic will validate that the passed in originalBaseResource is still valid at the point in time where it is set.
This results in the stacktrace ...

stop() failed: java.nio.file.ClosedFileSystemException
java.nio.file.ClosedFileSystemException
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.ensureOpen(ZipFileSystem.java:1628)
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.checkAccess(ZipFileSystem.java:560)
	at jdk.zipfs/jdk.nio.zipfs.ZipPath.checkAccess(ZipPath.java:892)
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.checkAccess(ZipFileSystemProvider.java:172)
	at java.base/java.nio.file.Files.isAccessible(Files.java:2597)
	at java.base/java.nio.file.Files.isReadable(Files.java:2632)
	at org.eclipse.jetty.util.resource.PathResource.isReadable(PathResource.java:307)
	at org.eclipse.jetty.util.resource.Resources.isReadable(Resources.java:79)
	at org.eclipse.jetty.server.handler.ContextHandler.setBaseResource(ContextHandler.java:884)
	at org.eclipse.jetty.ee10.webapp.WebInfConfiguration.deconfigure(WebInfConfiguration.java:99)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.stopContext(WebAppContext.java:1222)
	at org.eclipse.jetty.ee10.servlet.ServletContextHandler.doStop(ServletContextHandler.java:1070)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:132)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.stop(ContainerLifeCycle.java:182)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStop(ContainerLifeCycle.java:205)
	at org.eclipse.jetty.server.Handler$Abstract.doStop(Handler.java:403)
	at org.eclipse.jetty.server.Server.doStop(Server.java:648)

The ContextHandler.setBaseResource(Resource) should not be performing a resource validation step, that's something the ContextHandler.doStart() should be doing. I'll submit a PR for that.

We should also validate the reference counting going on.

@joakime joakime changed the title server.stop() throws ClosedFileSystemException when a resource is created Server.stop() and WebInfConfiguration.deconfigure() can throw a ClosedFileSystemException when restoring the original base resource Jul 25, 2023
@joakime
Copy link
Contributor

joakime commented Jul 25, 2023

The changes in PR #10147 seem to address this.

But more testing needs to occur with how WebAppContext performs with a start > stop > start scenario where the baseResource is replaced by WebInfConfiguration.deconfigure().

@mvysny
Copy link
Author

mvysny commented Jul 25, 2023

Thank you so much for digging into this this deep 🙏

joakime added a commit that referenced this issue Jul 26, 2023
…art()` (#10147)

* Issue #10134 - Delay Base Resource validation to `ContextHandler.doStart`
@janbartel
Copy link
Contributor

Issue was fixed in ad5c298

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side
Projects
None yet
Development

No branches or pull requests

3 participants