mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-87104 Stop skeleton generation processes when SDK is disposed
Register the indicator disposable under the SDK disposable (instead of PythonPluginDisposable) so that when the SDK is disposed the progress indicator is cancelled immediately. This terminates any external Python processes (e.g., skeleton generation) that are still running. In PyTargetsSkeletonGenerator, use the indicator-aware CapturingProcessRunner.runProcess(indicator) which polls indicator.isCanceled() every 10 ms and destroys the process when cancelled, instead of the no-arg runProcess() that waits indefinitely. Together these changes fix thread leaks in tests where SDK disposal during teardown left orphaned BaseDataReader threads from skeleton generation subprocesses. GitOrigin-RevId: a8f748ae0f03645a843ed3c62caa0260b2b9a33d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a29f7ae0bf
commit
96a42dbdb0
@@ -264,9 +264,15 @@ public final class PythonSdkUpdater {
|
||||
if (isSdkDisposed()) {
|
||||
return;
|
||||
}
|
||||
// This explicit cancellation should become unnecessary on migrating PythonSdkUpdater to coroutines and withBackgroundProgress
|
||||
// Cancel the indicator when the SDK is disposed to terminate any running processes (e.g., skeleton generation).
|
||||
// This explicit cancellation should become unnecessary on migrating PythonSdkUpdater to coroutines and withBackgroundProgress.
|
||||
Disposable indicatorDisposable = getIndicatorDisposable(indicator);
|
||||
Disposer.register(PythonPluginDisposable.getInstance(myProject), indicatorDisposable);
|
||||
if (mySdk instanceof Disposable sdkDisposable) {
|
||||
Disposer.register(sdkDisposable, indicatorDisposable);
|
||||
}
|
||||
else {
|
||||
Disposer.register(PythonPluginDisposable.getInstance(myProject), indicatorDisposable);
|
||||
}
|
||||
if (Trigger.LOG.isDebugEnabled()) {
|
||||
Trigger.LOG.debug(
|
||||
"Starting SDK refresh for '" + mySdk.getName() + "' triggered by " + Trigger.getCauseByTrace(myRequestData.myTraceback));
|
||||
@@ -294,7 +300,9 @@ public final class PythonSdkUpdater {
|
||||
}
|
||||
finally {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
Disposer.dispose(indicatorDisposable);
|
||||
if (!isSdkDisposed()) {
|
||||
Disposer.dispose(indicatorDisposable);
|
||||
}
|
||||
// restart code analysis
|
||||
DaemonCodeAnalyzer.getInstance(myProject).restart(this);
|
||||
}, myProject.getDisposed());
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.jetbrains.python.sdk.skeletons
|
||||
|
||||
import com.intellij.execution.process.CapturingProcessHandler
|
||||
import com.intellij.execution.process.CapturingProcessRunner
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.execution.target.TargetEnvironment
|
||||
import com.intellij.execution.target.TargetEnvironmentRequest
|
||||
@@ -13,6 +14,7 @@ import com.intellij.execution.target.value.getTargetDownloadPath
|
||||
import com.intellij.execution.target.value.getTargetUploadPath
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
@@ -128,7 +130,13 @@ class PyTargetsSkeletonGenerator(skeletonPath: String, pySdk: Sdk, currentFolder
|
||||
val commandPresentation = targetedCommandLine.getCommandPresentation(targetEnvironment)
|
||||
val capturingProcessHandler = CapturingProcessHandler(process, targetedCommandLine.charset, commandPresentation)
|
||||
listener?.let { capturingProcessHandler.addProcessListener(LineWiseProcessOutputListener.Adapter(it)) }
|
||||
val result = capturingProcessHandler.runProcess()
|
||||
val indicator = ProgressManager.getInstance().progressIndicator
|
||||
val result = if (indicator != null) {
|
||||
CapturingProcessRunner(capturingProcessHandler).runProcess(indicator)
|
||||
}
|
||||
else {
|
||||
capturingProcessHandler.runProcess()
|
||||
}
|
||||
|
||||
// XXX Make it automatic
|
||||
targetEnvironment.downloadVolumes.values.forEach { it.download(".", EmptyProgressIndicator()) }
|
||||
|
||||
Reference in New Issue
Block a user