Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More reliable shutdown of the EnsoContext to save resources #6468

Merged
merged 9 commits into from
May 2, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ class BuiltinTypesTest
context = new TestContext("Test")
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}
override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

def runCode(contextId: UUID, requestId: UUID, contents: String): Unit = {
val moduleName = "Enso_Test.Test.Main"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ class RuntimeAsyncCommandsTest
context = new TestContext("Test")
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}
override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "interrupt stopped execution context" in {
val moduleName = "Enso_Test.Test.Main"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ class RuntimeComponentsTest
context = new TestContext("Test")
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}
override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "load library extended by the component group" in {
val contextId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class RuntimeErrorsTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "return panic sentinels in method body" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ class RuntimeExecutionEnvironmentTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I added all these afterEach cleanups, running the whole sbt runtime-with-instruments/test started to randomly fail. Turned out I had to also f71557d - e.g. wait for the shutdown of the EnsoContext threads.

context.runtimeServerEmulator.terminate()
}

it should "panic when output context is not enabled" in {

val contextId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class RuntimeInstrumentTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "instrument simple expression" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ class RuntimeServerTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helps the "engine threads", but the test should also stop Akka, @4e6. Dmitry, if you know how to do that feel free to directly commit to this branch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not using Akka in runtime* projects. Only in the language-server and project-manager

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wrong, in fact, runtime tests are using Akka.

context.runtimeServerEmulator.terminate()
}

"RuntimeServer" should "push and pop functions on the stack" in {
val contents = context.Main.code
val mainFile = context.writeMain(contents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ class RuntimeStdlibTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "import Base modules" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class RuntimeSuggestionUpdatesTest
val Some(Api.Response(_, Api.InitializedNotification())) = context.receive
}

override protected def afterEach(): Unit = {
context.executionContext.context.close()
context.runtimeServerEmulator.terminate()
}

it should "send suggestion updates after file modification" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

final class ThreadExecutors {
private final EnsoContext context;
Expand All @@ -32,6 +34,17 @@ public void shutdown() {
while (it.hasNext()) {
var p = it.next().getKey();
p.shutdown();
boolean success;
try {
success = p.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
success = false;
}
if (!success) {
context
.getLogger()
.log(Level.WARNING, "Cannot shutdown {0} thread pool", it.next().getValue());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ final class JobExecutionEngine(
runtimeContext.executionService.getContext.getThreadManager
.interruptThreads()
jobExecutor.shutdownNow()
backgroundJobExecutor.shutdownNow()
}

/** Submit background jobs preserving the stable order. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ class RuntimeServerEmulator(
}
} else null
}

def terminate() = system.terminate()
}