Fix deadlock during HTTP server initialisation
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Mar 2024 09:14:38 +0000 (10:14 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Mar 2024 09:14:38 +0000 (10:14 +0100)
org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java

index e1c420b8287469bb698af791d04b9d87638563d9..52f97fd8d4224d71a7fe9ec7c26a5bfd985b8d5e 100644 (file)
@@ -63,12 +63,18 @@ public class CmsDeploymentImpl implements CmsDeployment {
 
        public void setHttpServer(HttpServer httpServer) {
                Objects.requireNonNull(httpServer);
-               this.httpServer.complete(httpServer);
-               // create contexts whose handles had already been published
-               for (String contextPath : httpHandlers.keySet()) {
-                       HttpHandler httpHandler = httpHandlers.get(contextPath);
-                       CmsAuthenticator authenticator = httpAuthenticators.get(contextPath);
-                       createHttpContext(contextPath, httpHandler, authenticator);
+               if (this.httpServer.isDone())
+                       throw new IllegalStateException("HTTP server is already set");
+               // create contexts whose handlers had already been published
+               synchronized (httpHandlers) {
+                       synchronized (httpAuthenticators) {
+                               this.httpServer.complete(httpServer);
+                               for (String contextPath : httpHandlers.keySet()) {
+                                       HttpHandler httpHandler = httpHandlers.get(contextPath);
+                                       CmsAuthenticator authenticator = httpAuthenticators.get(contextPath);
+                                       createHttpContext(contextPath, httpHandler, authenticator);
+                               }
+                       }
                }
        }
 
@@ -80,9 +86,13 @@ public class CmsDeploymentImpl implements CmsDeployment {
                }
                boolean isPublic = Boolean.parseBoolean(properties.get(CmsConstants.CONTEXT_PUBLIC));
                CmsAuthenticator authenticator = isPublic ? new PublicCmsAuthenticator() : new CmsAuthenticator();
-               httpHandlers.put(contextPath, httpHandler);
-               httpAuthenticators.put(contextPath, authenticator);
-               if (httpServer.join() == null) {
+               synchronized (httpHandlers) {
+                       synchronized (httpAuthenticators) {
+                               httpHandlers.put(contextPath, httpHandler);
+                               httpAuthenticators.put(contextPath, authenticator);
+                       }
+               }
+               if (!httpServer.isDone()) {
                        return;
                } else {
                        createHttpContext(contextPath, httpHandler, authenticator);
@@ -95,7 +105,9 @@ public class CmsDeploymentImpl implements CmsDeployment {
                                log.warn("Ignore HTTP context " + contextPath + " as we don't provide an HTTP server");
                        return;
                }
-               HttpContext httpContext = httpServer.join().createContext(contextPath);
+               if (!this.httpServer.isDone())
+                       throw new IllegalStateException("HTTP server is not set");
+               HttpContext httpContext = httpServer.resultNow().createContext(contextPath);
                // we want to set the authenticator BEFORE the handler actually becomes active
                httpContext.setAuthenticator(authenticator);
                httpContext.setHandler(httpHandler);
@@ -107,9 +119,9 @@ public class CmsDeploymentImpl implements CmsDeployment {
                if (contextPath == null)
                        return; // ignore silently
                httpHandlers.remove(contextPath);
-               if (httpServer.join() == null)
+               if (!httpServer.isDone())
                        return;
-               httpServer.join().removeContext(contextPath);
+               httpServer.resultNow().removeContext(contextPath);
                log.debug(() -> "Removed handler " + contextPath + " : " + httpHandler.getClass().getName());
        }