]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7168 do not recreate HardStopWatcherThread for realiability
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 14 Jan 2016 11:30:49 +0000 (12:30 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 18 Jan 2016 10:16:44 +0000 (11:16 +0100)
this can be implemented but at the depend of IOs since a new File will be open every 500ms when the watcher looks at the sharedMemory

server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java
server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/Monitor.java

index 019d6388cd9c9e1ed63f1e05b3860d45ef3187c4..403ec9a3b60b11f2d288091980e1c135a35607b2 100644 (file)
@@ -49,10 +49,6 @@ public class JavaProcessLauncher {
     allProcessesCommands.close();
   }
 
-  public ProcessCommands getProcessCommand(int processNumber, boolean clean) {
-    return allProcessesCommands.getProcessCommand(processNumber, clean);
-  }
-
   ProcessRef launch(JavaCommand command) {
     Process process = null;
     try {
index 481495b7d146520225b5acc4fbe83ddaecccae79..5df75054ab98e3c16f1c1e81403767479bebe28f 100644 (file)
@@ -29,6 +29,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonar.process.DefaultProcessCommands;
 import org.sonar.process.Lifecycle;
 import org.sonar.process.Lifecycle.State;
 import org.sonar.process.ProcessCommands;
@@ -91,6 +92,12 @@ public class Monitor {
     // intercepts CTRL-C
     Runtime.getRuntime().addShutdownHook(shutdownHook);
 
+    // start watching for stop requested by other process (eg. orchestrator) if enabled
+    if (watchForHardStop) {
+      this.hardStopWatcher = new HardStopWatcherThread();
+      this.hardStopWatcher.start();
+    }
+
     // start watching for restart requested by child process
     this.restartWatcher.start();
 
@@ -105,24 +112,9 @@ public class Monitor {
 
       startAndMonitorProcesses();
       stopIfAnyProcessDidNotStart();
-      watchForHardStop();
     }
   }
 
-  private void watchForHardStop() {
-    if (!watchForHardStop) {
-      return;
-    }
-
-    if (this.hardStopWatcher != null) {
-      this.hardStopWatcher.stopWatching();
-      awaitTermination(this.hardStopWatcher);
-    }
-    ProcessCommands processCommand = this.launcher.getProcessCommand(CURRENT_PROCESS_NUMBER, true);
-    this.hardStopWatcher = new HardStopWatcherThread(processCommand);
-    this.hardStopWatcher.start();
-  }
-
   private void resetFileSystem() {
     // since JavaLauncher depends on temp directory, which is reset below, we need to close it first
     closeJavaLauncher();
@@ -134,6 +126,13 @@ public class Monitor {
     }
   }
 
+  private void closeJavaLauncher() {
+    if (this.launcher != null) {
+      this.launcher.close();
+      this.launcher = null;
+    }
+  }
+
   private void startAndMonitorProcesses() {
     File tempDir = fileSystem.getTempDir();
     this.launcher = new JavaProcessLauncher(TIMEOUTS, tempDir);
@@ -149,13 +148,6 @@ public class Monitor {
     }
   }
 
-  private void closeJavaLauncher() {
-    if (this.launcher != null) {
-      this.launcher.close();
-      this.launcher = null;
-    }
-  }
-
   private void monitor(ProcessRef processRef) {
     // physically watch if process is alive
     WatcherThread watcherThread = new WatcherThread(processRef, this);
@@ -345,33 +337,60 @@ public class Monitor {
   }
 
   public class HardStopWatcherThread extends Thread {
-    private final ProcessCommands processCommands;
-    private boolean watch = true;
 
-    public HardStopWatcherThread(ProcessCommands processCommands) {
+    public HardStopWatcherThread() {
       super("Hard stop watcher");
-      this.processCommands = processCommands;
     }
 
     @Override
     public void run() {
-      while (watch && lifecycle.getState() != Lifecycle.State.STOPPED) {
-        if (processCommands.askedForStop()) {
+      while (lifecycle.getState() != Lifecycle.State.STOPPED) {
+        if (askedForStop()) {
           trace("Stopping process");
           Monitor.this.stop();
         } else {
-          try {
-            Thread.sleep(WATCH_DELAY_MS);
-          } catch (InterruptedException ignored) {
-            // keep watching
-          }
+          delay();
         }
       }
     }
 
-    public void stopWatching() {
-      this.watch = false;
+    private boolean askedForStop() {
+      File tempDir = fileSystem.getTempDir();
+      try (DefaultProcessCommands processCommands = new DefaultProcessCommands(tempDir, CURRENT_PROCESS_NUMBER, false)) {
+        if (processCommands.askedForStop()) {
+          return true;
+        }
+      } catch (IllegalArgumentException e) {
+        // DefaultProcessCommand currently wraps IOException into a IllegalArgumentException
+        // accessing the shared memory file may fail if a restart is in progress and the temp directory
+        // is currently deleted and not yet recreated
+        if (e.getCause() instanceof IOException) {
+          ignore((IOException) e.getCause());
+        } else {
+          rethrow(e);
+        }
+      } catch (Exception e) {
+        rethrow(e);
+      }
+      return false;
+    }
+
+    private void ignore(IOException e) {
+      trace("HardStopWatcherThread: Error checking stop flag in shared memory. Ignoring. Keep on watching.", e);
+    }
+
+    private void rethrow(Exception e) {
+      throw new RuntimeException("Unexpected error occurred while watch for stop flag in shared memory", e);
     }
+
+    private void delay() {
+      try {
+        Thread.sleep(WATCH_DELAY_MS);
+      } catch (InterruptedException ignored) {
+        // keep watching
+      }
+    }
+
   }
 
   private void stopProcesses() {