diff --git a/terminal/plugins/org.eclipse.tm.terminal.view.ui/META-INF/MANIFEST.MF b/terminal/plugins/org.eclipse.tm.terminal.view.ui/META-INF/MANIFEST.MF index d269bd9643f..18ad8011105 100644 --- a/terminal/plugins/org.eclipse.tm.terminal.view.ui/META-INF/MANIFEST.MF +++ b/terminal/plugins/org.eclipse.tm.terminal.view.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.tm.terminal.view.ui;singleton:=true -Bundle-Version: 4.9.0.qualifier +Bundle-Version: 4.9.1.qualifier Bundle-Activator: org.eclipse.tm.terminal.view.ui.activator.UIPlugin Bundle-Vendor: %providerName Require-Bundle: org.eclipse.core.expressions;bundle-version="3.4.400", diff --git a/terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/local/showin/detectors/DetectWSL.java b/terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/local/showin/detectors/DetectWSL.java index 68fb6bb7533..2d07cd0ba86 100644 --- a/terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/local/showin/detectors/DetectWSL.java +++ b/terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/local/showin/detectors/DetectWSL.java @@ -24,16 +24,19 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.tm.terminal.view.ui.interfaces.IExternalExecutablesProperties; import org.eclipse.tm.terminal.view.ui.local.showin.IDetectExternalExecutable; public class DetectWSL implements IDetectExternalExecutable { - /** - * Don't access directly, use {@link #getEntries()} - */ - List> result = null; + private List> result = null; + private WslDetectJob detectJob = null; @Override public boolean hasEntries() { @@ -55,57 +58,94 @@ public class DetectWSL implements IDetectExternalExecutable { } private synchronized List> getEntries() { - if (result == null) { - result = Collections.emptyList(); - if (Platform.OS_WIN32.equals(Platform.getOS())) { - String windir = System.getenv("windir"); //$NON-NLS-1$ - if (windir == null) { - return result; - } - String wsl = windir + "\\System32\\wsl.exe"; //$NON-NLS-1$ - if (!Files.isExecutable(Paths.get(wsl))) { - return result; - } - - ProcessBuilder pb = new ProcessBuilder(wsl, "--list", "--quiet"); //$NON-NLS-1$ //$NON-NLS-2$ - try { - Process process = pb.start(); - try (InputStream is = process.getErrorStream()) { - // drain the error stream - if (is.readAllBytes().length != 0) { - return result; - } - } - - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_16LE))) { - result = new ArrayList<>(); - String line = null; - while ((line = reader.readLine()) != null) { - String distribution = line.trim(); - if (distribution.isBlank()) { - continue; - } - // docker-desktop entries are not "real" so shouldn't be shown in UI - if (distribution.startsWith("docker-desktop")) { //$NON-NLS-1$ - continue; - } - - String name = distribution + " (WSL)"; //$NON-NLS-1$ - Map m = new HashMap<>(); - m.put(IExternalExecutablesProperties.PROP_NAME, name); - m.put(IExternalExecutablesProperties.PROP_PATH, wsl); - m.put(IExternalExecutablesProperties.PROP_ARGS, "--distribution " + distribution); //$NON-NLS-1$ - m.put(IExternalExecutablesProperties.PROP_TRANSLATE, Boolean.TRUE.toString()); - result.add(m); - } - } - - } catch (IOException e) { - } + // getEntries can be called in many contexts, even from within + // menu creation (see Bug 574519). Therefore we spawn a job to + // get the real entries, which means until the job is done, this + // method will return no entries. + if (result != null) { + return result; + } + if (detectJob == null) { + detectJob = new WslDetectJob(); + detectJob.schedule(); + } + try { + if (detectJob.join(10, null)) { + result = detectJob.result; + detectJob = null; + } else { + return Collections.emptyList(); } + } catch (OperationCanceledException | InterruptedException e) { + result = Collections.emptyList(); + detectJob = null; } return result; } + private static class WslDetectJob extends Job { + private List> result = null; + + public WslDetectJob() { + super("Detect WSL Instances"); //$NON-NLS-1$ + setSystem(true); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + if (result == null) { + result = Collections.emptyList(); + if (Platform.OS_WIN32.equals(Platform.getOS())) { + String windir = System.getenv("windir"); //$NON-NLS-1$ + if (windir == null) { + return Status.OK_STATUS; + } + String wsl = windir + "\\System32\\wsl.exe"; //$NON-NLS-1$ + if (!Files.isExecutable(Paths.get(wsl))) { + return Status.OK_STATUS; + } + + ProcessBuilder pb = new ProcessBuilder(wsl, "--list", "--quiet"); //$NON-NLS-1$ //$NON-NLS-2$ + try { + Process process = pb.start(); + try (InputStream is = process.getErrorStream()) { + // drain the error stream + if (is.readAllBytes().length != 0) { + return Status.OK_STATUS; + } + } + + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_16LE))) { + result = new ArrayList<>(); + String line = null; + while ((line = reader.readLine()) != null) { + String distribution = line.trim(); + if (distribution.isBlank()) { + continue; + } + // docker-desktop entries are not "real" so shouldn't be shown in UI + if (distribution.startsWith("docker-desktop")) { //$NON-NLS-1$ + continue; + } + + String name = distribution + " (WSL)"; //$NON-NLS-1$ + Map m = new HashMap<>(); + m.put(IExternalExecutablesProperties.PROP_NAME, name); + m.put(IExternalExecutablesProperties.PROP_PATH, wsl); + m.put(IExternalExecutablesProperties.PROP_ARGS, "--distribution " + distribution); //$NON-NLS-1$ + m.put(IExternalExecutablesProperties.PROP_TRANSLATE, Boolean.TRUE.toString()); + result.add(m); + } + } + + } catch (IOException e) { + } + } + } + return Status.OK_STATUS; + } + + } + }