Skip to content

Commit 6e071b5

Browse files
committed
fix(devins-lang): fix memory leak in DevInsProgramRunner
Problem: DevInsProgramRunner was implementing Disposable and registering a MessageBusConnection with 'this' as parent, but the runner itself was never properly disposed, causing memory leak warnings. Solution: - Remove Disposable interface from DevInsProgramRunner - Connect to project's message bus instead of application's - Register the connection with the project as parent disposable - This ensures proper cleanup when the project is closed The connection is now tied to the project lifecycle instead of the runner's lifecycle, which is the correct pattern for ProgramRunner implementations.
1 parent 4f86ef1 commit 6e071b5

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/run/DevInsProgramRunner.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ import com.intellij.execution.runners.ExecutionEnvironment
1313
import com.intellij.execution.runners.GenericProgramRunner
1414
import com.intellij.execution.runners.showRunContent
1515
import com.intellij.execution.ui.RunContentDescriptor
16-
import com.intellij.openapi.Disposable
1716
import com.intellij.openapi.application.ApplicationManager
18-
import com.intellij.openapi.fileEditor.FileDocumentManager
17+
import com.intellij.openapi.util.Disposer
18+
import com.intellij.util.messages.MessageBusConnection
1919
import kotlinx.coroutines.launch
2020
import java.util.concurrent.atomic.AtomicReference
2121

22-
class DevInsProgramRunner : GenericProgramRunner<RunnerSettings>(), Disposable {
22+
class DevInsProgramRunner : GenericProgramRunner<RunnerSettings>() {
2323
private val RUNNER_ID: String = "DevInsProgramRunner"
2424

25-
private val connection = ApplicationManager.getApplication().messageBus.connect(this)
26-
25+
// Use lazy initialization to avoid memory leak - connection is created per execution
26+
// and tied to the project's lifecycle, not the runner's lifecycle
27+
private var connection: MessageBusConnection? = null
2728
private var isSubscribed = false
2829

2930
override fun getRunnerId(): String = RUNNER_ID
@@ -40,7 +41,15 @@ class DevInsProgramRunner : GenericProgramRunner<RunnerSettings>(), Disposable {
4041

4142
ApplicationManager.getApplication().invokeAndWait {
4243
if (!isSubscribed) {
43-
connection.subscribe(DevInsRunListener.TOPIC, object : DevInsRunListener {
44+
// Connect to project's message bus instead of application's
45+
// This ensures proper disposal when the project is closed
46+
val projectConnection = environment.project.messageBus.connect()
47+
connection = projectConnection
48+
49+
// Register for disposal with the project
50+
Disposer.register(environment.project, projectConnection)
51+
52+
projectConnection.subscribe(DevInsRunListener.TOPIC, object : DevInsRunListener {
4453
override fun runFinish(
4554
allOutput: String,
4655
llmOutput: String,
@@ -67,8 +76,4 @@ class DevInsProgramRunner : GenericProgramRunner<RunnerSettings>(), Disposable {
6776

6877
return result.get()
6978
}
70-
71-
override fun dispose() {
72-
connection.disconnect()
73-
}
7479
}

0 commit comments

Comments
 (0)