diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2019-09-05 12:33:48 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-09-06 20:21:05 +0200 |
commit | b08e4d46d652a960a168318f6cace9d33d9ceebc (patch) | |
tree | c5427912b62372fd7a4685798fb64f7123b94dbe /server/sonar-main | |
parent | 306cc616fcf6a3e2d624ddfd19eb948351c76593 (diff) | |
download | sonarqube-b08e4d46d652a960a168318f6cace9d33d9ceebc.tar.gz sonarqube-b08e4d46d652a960a168318f6cace9d33d9ceebc.zip |
do not call stop finalization code without checking lifeCycle state
this avoid having multiple thread call the stope finalization concurrently and killing each other, which is unpredictable and very hard to reproduce behavior
Diffstat (limited to 'server/sonar-main')
2 files changed, 12 insertions, 22 deletions
diff --git a/server/sonar-main/src/main/java/org/sonar/application/process/ManagedProcessHandler.java b/server/sonar-main/src/main/java/org/sonar/application/process/ManagedProcessHandler.java index 234239e5bec..508c73b5e0b 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/process/ManagedProcessHandler.java +++ b/server/sonar-main/src/main/java/org/sonar/application/process/ManagedProcessHandler.java @@ -104,7 +104,7 @@ public class ManagedProcessHandler { hardStop(); } else { // enforce stop and clean-up even if process has been quickly stopped - stopForcibly(); + finalizeStop(); } } else { // already stopping or stopped @@ -123,7 +123,7 @@ public class ManagedProcessHandler { LOG.info("{} failed to stop in a quick fashion. Killing it.", processId.getKey()); } // enforce stop and clean-up even if process has been quickly stopped - stopForcibly(); + finalizeStop(); } else { // already stopping or stopped waitForDown(); @@ -178,7 +178,7 @@ public class ManagedProcessHandler { return new InterruptedException(errorMessage); } - public void stopForcibly() { + private void finalizeStop() { interrupt(eventWatcher); interrupt(stopWatcher); if (process != null) { @@ -253,7 +253,15 @@ public class ManagedProcessHandler { Thread.currentThread().interrupt(); // stop watching process } - stopForcibly(); + // since process is already stopped, this will only finalize the stop sequence + // call hardStop() rather than finalizeStop() directly because hardStop() checks lifeCycle state and this + // avoid running to concurrent stop finalization pieces of code + try { + hardStop(); + } catch (InterruptedException e) { + LOG.debug("Interrupted while stopping [{}] after process ended", processId.getKey(), e); + Thread.currentThread().interrupt(); + } } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/process/ManagedProcessHandlerTest.java b/server/sonar-main/src/test/java/org/sonar/application/process/ManagedProcessHandlerTest.java index 467c6bfbc55..5b18ee1d7cb 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/process/ManagedProcessHandlerTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/process/ManagedProcessHandlerTest.java @@ -174,24 +174,6 @@ public class ManagedProcessHandlerTest { } @Test - public void stopForcibly_stops_the_process_without_graceful_request_for_stop() { - ManagedProcessHandler underTest = newHanderBuilder(A_PROCESS_ID).build(); - - try (TestManagedProcess testProcess = new TestManagedProcess()) { - underTest.start(() -> testProcess); - - underTest.stopForcibly(); - assertThat(underTest.getState()).isEqualTo(ManagedProcessLifecycle.State.STOPPED); - assertThat(testProcess.askedForHardStop).isFalse(); - assertThat(testProcess.destroyedForcibly).isTrue(); - - // second execution of stopForcibly does nothing. It's still stopped. - underTest.stopForcibly(); - assertThat(underTest.getState()).isEqualTo(ManagedProcessLifecycle.State.STOPPED); - } - } - - @Test public void process_stops_after_graceful_request_for_stop() throws Exception { ProcessLifecycleListener listener = mock(ProcessLifecycleListener.class); ManagedProcessHandler underTest = newHanderBuilder(A_PROCESS_ID) |