]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20389 Prevent race condition from happening when servlet is starting up
authorAurelien Poscia <aurelien.poscia@sonarsource.com>
Tue, 19 Sep 2023 13:11:11 +0000 (15:11 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 25 Sep 2023 20:02:47 +0000 (20:02 +0000)
server/sonar-webserver/src/main/java/org/sonar/server/platform/web/ApiV2Servlet.java
server/sonar-webserver/src/test/java/org/sonar/server/platform/web/ApiV2ServletTest.java

index 9603c2d70a81d6b3aac84bddf81eaf6a8042f07e..6daa36d58c920c3cf139232af4c957a53113b0d2 100644 (file)
@@ -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();
index 14f64c3599ca13cb165ada4174072d563fef723e..2e43c0bac534b32d6b03fe14440f69a010825193 100644 (file)
@@ -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();