Skip to content

Commit 84ab919

Browse files
committed
Inline servers can respin on zap and restart while trying to be shutdown. Check if the the thread is running before respin.
1 parent 9625b0e commit 84ab919

File tree

5 files changed

+32
-53
lines changed

5 files changed

+32
-53
lines changed

galvan-support/src/main/java/org/terracotta/testing/rules/BasicExternalCluster.java

Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -155,30 +155,10 @@ protected void before() throws Throwable {
155155
}
156156

157157
@Override
158-
public TestManager getTestManager() {
159-
return new TestManager() {
160-
@Override
161-
public void testFinished() {
162-
stateManager.setTestDidPassIfNotFailed();
163-
}
164-
165-
@Override
166-
public void testDidFail(GalvanFailureException failure) {
167-
stateManager.testDidFail(failure);
168-
}
169-
170-
@Override
171-
public boolean isComplete() throws GalvanFailureException {
172-
return stateManager.checkDidPass();
173-
}
174-
};
158+
public ClusterInfo getClusterInfo() {
159+
return this.cluster.getClusterInfo();
175160
}
176161

177-
@Override
178-
public ClusterInfo getClusterInfo() {
179-
return this.cluster.getClusterInfo();
180-
}
181-
182162
private void internalStart(CompletableFuture<Void> checker) throws Throwable {
183163
VerboseLogger harnessLogger = new VerboseLogger(System.out, null);
184164
VerboseLogger fileHelpersLogger = new VerboseLogger(null, null);
@@ -269,34 +249,30 @@ public void run() {
269249
stateManager.waitForFinish();
270250
didPass = true;
271251
} catch (GalvanFailureException e) {
272-
e.printStackTrace();
273252
checker.completeExceptionally(e);
274253
didPass = false;
275254
} finally {
276-
// Whether we passed or failed, bring everything down.
255+
setSafeForRun(false);
277256
try {
278-
interlock.forceShutdown();
279-
} catch (Exception e) {
280-
e.printStackTrace();
281-
didPass = false;
282-
} finally {
283-
setSafeForRun(false);
284-
285-
serverPortRefs.forEach(PortManager.PortRef::close);
286-
groupPortRefs.forEach(PortManager.PortRef::close);
287-
debugPortRefs.stream().filter(Objects::nonNull).forEach(PortManager.PortRef::close);
288-
289-
if (!didPass) {
290-
// Typically, we want to interrupt the thread running as the "client" as it might be stuck in a connection
291-
// attempt, etc. When Galvan is run in the purely multi-process mode, this is typically where all
292-
// sub-processes would be terminated. Since we are running the client as another thread, in-process, the
293-
// best we can do is interrupt it from a lower-level blocking call.
294-
// NOTE: the "client" is also the thread which created us and will join on our termination, before
295-
// returning back to the user code so it is possible that this interruption could be experienced in its
296-
// join() call (in which case, we can safely ignore it).
297-
isInterruptingClient = true;
298-
clientThread.interrupt();
299-
}
257+
// make sure all servers are down before releasing ports
258+
interlock.waitForAllServerTerminated();
259+
} catch (GalvanFailureException ge) {
260+
261+
}
262+
serverPortRefs.forEach(PortManager.PortRef::close);
263+
groupPortRefs.forEach(PortManager.PortRef::close);
264+
debugPortRefs.stream().filter(Objects::nonNull).forEach(PortManager.PortRef::close);
265+
266+
if (!didPass) {
267+
// Typically, we want to interrupt the thread running as the "client" as it might be stuck in a connection
268+
// attempt, etc. When Galvan is run in the purely multi-process mode, this is typically where all
269+
// sub-processes would be terminated. Since we are running the client as another thread, in-process, the
270+
// best we can do is interrupt it from a lower-level blocking call.
271+
// NOTE: the "client" is also the thread which created us and will join on our termination, before
272+
// returning back to the user code so it is possible that this interruption could be experienced in its
273+
// join() call (in which case, we can safely ignore it).
274+
isInterruptingClient = true;
275+
clientThread.interrupt();
300276
}
301277
}
302278
}
@@ -319,7 +295,6 @@ private void internalStop() {
319295
try {
320296
interlock.ignoreServerCrashes(true);
321297
interlock.forceShutdown();
322-
interlock.waitForAllServerTerminated();
323298
} catch (GalvanFailureException gf) {
324299
stateManager.testDidFail(gf);
325300
}

galvan-support/src/main/java/org/terracotta/testing/rules/Cluster.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ public abstract class Cluster extends ExternalResource {
3838

3939
public abstract ClusterControl getClusterControl();
4040

41-
public abstract TestManager getTestManager();
42-
4341
public abstract void expectCrashes(boolean yes);
4442

4543
public abstract CompletionStage<Void> manualStart(String display);

galvan/src/main/java/org/terracotta/testing/master/InlineServer.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ public void stop() throws InterruptedException {
163163
serverLogger.output("Crashing server process: " + serverThread);
164164
// Mark this as expected.
165165
this.setCrashExpected(true);
166-
boolean result = serverThread.shutdown();
166+
boolean result;
167+
do {
168+
result = serverThread.shutdown();
169+
} while (!result);
167170
serverLogger.output("Server Stop Command Result: " + result);
168171
}
169172
} finally {
@@ -224,7 +227,7 @@ public void run() {
224227
try (OutputStream events = buildEventingStream(stdout)) {
225228
if (initializeServer(events)) {
226229
serverLogger.output("starting server");
227-
returnValue = (Boolean)invokeOnObject(server, "waitUntilShutdown");
230+
returnValue = (Boolean)invokeOnObject(server, "waitUntilShutdown") && isRunning();
228231
didTerminateWithStatus(returnValue);
229232
serverLogger.output("server process exit. restarting:" + returnValue);
230233
} else {
@@ -246,6 +249,10 @@ private Object getServerObject() {
246249
return server;
247250
}
248251

252+
private synchronized boolean isRunning() {
253+
return running;
254+
}
255+
249256
private synchronized boolean initializeServer(OutputStream out) throws Exception {
250257
server = startIsolatedServer(serverWorkingDir, serverInstall, out, cmd, serverProperties);
251258
running = server != null;

galvan/src/main/java/org/terracotta/testing/master/ServerInstance.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.terracotta.testing.common.Assert;
3232
import org.terracotta.testing.common.SimpleEventingStream;
3333
import org.terracotta.testing.logging.ContextualLogger;
34-
import org.terracotta.testing.logging.VerboseManager;
3534
import static org.terracotta.testing.master.ServerMode.ACTIVE;
3635

3736

@@ -102,6 +101,7 @@ protected synchronized boolean isCrashExpected() {
102101
return this.isCrashExpected;
103102
}
104103

104+
@Override
105105
public synchronized void setCrashExpected(boolean expect) {
106106
this.isCrashExpected = expect;
107107
}

galvan/src/main/java/org/terracotta/testing/master/StateInterlock.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ private void safeStop(IGalvanServer server) {
236236
this.logger.output("< safeStop " + server.toString());
237237
this.logger.output("Stopping " + server);
238238
server.stop();
239-
server.waitForState(ServerMode.TERMINATED);
240239
this.logger.output("> safeStop " + server.toString() + " " + (System.currentTimeMillis() - start) + "ms");
241240
} catch (InterruptedException e) {
242241
// Not expected in this usage - we are shutting down.

0 commit comments

Comments
 (0)