From f48dd4c12563e0026e0d1ab3c07b330ccf4d0d5e Mon Sep 17 00:00:00 2001 From: Aurelien Poscia Date: Tue, 19 Sep 2023 15:11:11 +0200 Subject: [PATCH] SONAR-20389 Prevent race condition from happening when servlet is starting up --- .../org/sonar/server/platform/web/ApiV2Servlet.java | 13 ++++++++++++- .../sonar/server/platform/web/ApiV2ServletTest.java | 8 +++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/web/ApiV2Servlet.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/web/ApiV2Servlet.java index 9603c2d70a8..6daa36d58c9 100644 --- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/web/ApiV2Servlet.java +++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/web/ApiV2Servlet.java @@ -21,6 +21,7 @@ package org.sonar.server.platform.web; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; +import java.util.concurrent.CountDownLatch; import java.util.function.Function; import javax.servlet.Servlet; import javax.servlet.ServletConfig; @@ -42,6 +43,8 @@ public class ApiV2Servlet implements Servlet { private DispatcherServlet dispatcherLevel4 = null; private DispatcherServlet dispatcherSafeMode = null; + private final CountDownLatch safeModeInitializationCompletedLatch = new CountDownLatch(2); + public ApiV2Servlet() { this.servletProvider = DispatcherServlet::new; } @@ -69,11 +72,13 @@ public class ApiV2Servlet implements Servlet { } if (dispatcherSafeMode != null) { dispatcherSafeMode.init(config); + safeModeInitializationCompletedLatch.countDown(); } } public void initDispatcherSafeMode(PlatformLevel platformLevel) { - this.dispatcherSafeMode = initDispatcherServlet(platformLevel, SafeModeWebConfig.class); + dispatcherSafeMode = initDispatcherServlet(platformLevel, SafeModeWebConfig.class); + safeModeInitializationCompletedLatch.countDown(); } public void initDispatcherLevel4(PlatformLevel platformLevel) { @@ -116,6 +121,12 @@ public class ApiV2Servlet implements Servlet { private void destroyDispatcherSafeMode() { if (dispatcherSafeMode != null) { + try { + safeModeInitializationCompletedLatch.await(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(ie); + } DispatcherServlet dispatcherToDestroy = dispatcherSafeMode; dispatcherSafeMode = null; dispatcherToDestroy.destroy(); diff --git a/server/sonar-webserver/src/test/java/org/sonar/server/platform/web/ApiV2ServletTest.java b/server/sonar-webserver/src/test/java/org/sonar/server/platform/web/ApiV2ServletTest.java index 14f64c3599c..2e43c0bac53 100644 --- a/server/sonar-webserver/src/test/java/org/sonar/server/platform/web/ApiV2ServletTest.java +++ b/server/sonar-webserver/src/test/java/org/sonar/server/platform/web/ApiV2ServletTest.java @@ -97,8 +97,8 @@ public class ApiV2ServletTest { DispatcherServlet mockDispatcherServletLevel4 = mock(DispatcherServlet.class); underTest.setServletProvider(context -> mockDispatcherServletSafeMode); - underTest.init(mock(ServletConfig.class)); underTest.initDispatcherSafeMode(mockPlatformLevel); + underTest.init(mock(ServletConfig.class)); ServletRequest mockRequest1 = mock(ServletRequest.class); ServletResponse mockResponse1 = mock(ServletResponse.class); underTest.service(mockRequest1, mockResponse1); @@ -141,13 +141,14 @@ public class ApiV2ServletTest { } @Test - public void initDispatcherServlet_initLevel4ShouldDestroySafeMode() { + public void initDispatcherServlet_initLevel4ShouldDestroySafeMode() throws ServletException { PlatformLevel mockPlatformLevel = getMockPlatformLevel(); ApiV2Servlet underTest = new ApiV2Servlet(); DispatcherServlet mockDispatcherServletSafeMode = mock(DispatcherServlet.class); underTest.setServletProvider(context -> mockDispatcherServletSafeMode); underTest.initDispatcherSafeMode(mockPlatformLevel); + underTest.init(mock(ServletConfig.class)); underTest.setServletProvider(context -> mock(DispatcherServlet.class)); @@ -171,13 +172,14 @@ public class ApiV2ServletTest { } @Test - public void destroy_shouldDestroyDispatcherSafeMode() { + public void destroy_shouldDestroyDispatcherSafeMode() throws ServletException { PlatformLevel mockPlatformLevel = getMockPlatformLevel(); ApiV2Servlet underTest = new ApiV2Servlet(); DispatcherServlet mockDispatcherServletSafeMode = mock(DispatcherServlet.class); underTest.setServletProvider(context -> mockDispatcherServletSafeMode); underTest.initDispatcherSafeMode(mockPlatformLevel); + underTest.init(mock(ServletConfig.class)); underTest.destroy(); -- 2.39.5