From 91ac20e2d89e3d5d5df1d9627e1471288a315a54 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 14 Jan 2016 12:30:49 +0100 Subject: [PATCH] SONAR-7168 do not recreate HardStopWatcherThread for realiability 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 --- .../process/monitor/JavaProcessLauncher.java | 4 - .../org/sonar/process/monitor/Monitor.java | 89 +++++++++++-------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java index 019d6388cd9..403ec9a3b60 100644 --- a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java +++ b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java @@ -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 { diff --git a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/Monitor.java b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/Monitor.java index 481495b7d14..5df75054ab9 100644 --- a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/Monitor.java +++ b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/Monitor.java @@ -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() { -- 2.39.5