This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch SLING-11824
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git
The following commit(s) were added to refs/heads/SLING-11824 by this push:
new e3eb182 SLING-11824 : Deadlock during repository restart
e3eb182 is described below
commit e3eb182770ab99fa49204fd80d8d78de4a3e1937
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Tue Apr 11 17:58:21 2023 +0200
SLING-11824 : Deadlock during repository restart
---
.../engine/impl/helper/SlingServletContext.java | 92 ++++++++++++++++------
1 file changed, 68 insertions(+), 24 deletions(-)
diff --git
a/src/main/java/org/apache/sling/engine/impl/helper/SlingServletContext.java
b/src/main/java/org/apache/sling/engine/impl/helper/SlingServletContext.java
index 3b60d35..d8bcb43 100644
--- a/src/main/java/org/apache/sling/engine/impl/helper/SlingServletContext.java
+++ b/src/main/java/org/apache/sling/engine/impl/helper/SlingServletContext.java
@@ -116,6 +116,9 @@ public class SlingServletContext implements ServletContext,
ServletContextListen
private volatile String configuredServerInfo;
+ // counter to synchronize the init and destroy methods
+ private volatile long initCounter;
+
private volatile ServletContext servletContext;
private volatile ServiceRegistration<ServletContext> registration;
@@ -199,37 +202,78 @@ public class SlingServletContext implements
ServletContext, ServletContextListen
}
}
- @Override
- public void contextDestroyed(final ServletContextEvent sce) {
- synchronized ( this ) {
- this.servletContext = null;
- this.setServerInfo();
- if ( this.registration != null ) {
- this.registration.unregister();
- this.registration = null;
- }
+ private void runAsync(final Runnable r) {
+ final Thread thread = new Thread(r, "SlingServletContext
registration");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ private ServiceRegistration<ServletContext> registerServletContext() {
+ final Dictionary<String, Object> props = new Hashtable<String,
Object>();
+ props.put("name", SlingHttpContext.SERVLET_CONTEXT_NAME); // property
to identify this context
+ return bundleContext.registerService(ServletContext.class,
SlingServletContext.this, props);
+ }
+
+ private void unregisterServletContext(final
ServiceRegistration<ServletContext> reg) {
+ try {
+ reg.unregister();
+ } catch (final IllegalStateException ise) {
+ // ignore
}
}
@Override
public void contextInitialized(final ServletContextEvent sce) {
- this.servletContext = sce.getServletContext();
- this.setServerInfo();
- // async registreation
- final Thread thread = new Thread("SlingServletContext registration") {
- @Override
- public void run() {
- synchronized (SlingServletContext.this) {
- if ( servletContext != null ) {
- final Dictionary<String, Object> props = new
Hashtable<String, Object>();
- props.put("name",
SlingHttpContext.SERVLET_CONTEXT_NAME); // property to identify this context
- registration =
bundleContext.registerService(ServletContext.class, SlingServletContext.this,
props);
+ final ServletContext delegatee;
+ final long counter;
+ synchronized ( this ) {
+ this.servletContext = sce.getServletContext();
+ this.setServerInfo();
+ delegatee = this.servletContext;
+ this.initCounter++;
+ counter = this.initCounter;
+ }
+ if ( delegatee != null ) {
+ // async registration
+ this.runAsync(() -> {
+ final boolean register;
+ synchronized ( SlingServletContext.this ) {
+ register = SlingServletContext.this.servletContext ==
delegatee;
+ }
+ if ( register ) {
+ final ServiceRegistration<ServletContext> reg =
registerServletContext();
+ boolean immediatelyUnregister = false;
+ synchronized ( SlingServletContext.this ) {
+ if ( SlingServletContext.this.initCounter == counter )
{
+ SlingServletContext.this.registration = reg;
+ } else {
+ immediatelyUnregister = true;
+ }
+ }
+ if ( immediatelyUnregister ) {
+ unregisterServletContext(reg);
}
}
- }
- };
- thread.setDaemon(true);
- thread.start();
+ });
+ }
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent sce) {
+ final ServiceRegistration<ServletContext> reg;
+ synchronized ( this ) {
+ this.initCounter++;
+ reg = this.registration;
+ this.registration = null;
+ this.servletContext = null;
+ this.setServerInfo();
+ }
+ if ( reg != null ) {
+ // async unregistration
+ this.runAsync(() -> {
+ unregisterServletContext(reg);
+ });
+ }
}
/**