terminal: Fix terminal cloning on WSL (#39552)

Should close #39428

The working directory of the `wsl.exe` program is set to a Linux path,
which is invalid on the Windows side, causing the terminal to crash. The
first spawn works because there is no active terminal view, allowing a
new shell (which checks for the remote) to be created. I cannot explain
why it works on SSH remote clients, but I may be missing something in
the remote connection implementation.

I don't have a Windows machine to test this, so I would appreciate
someone testing it. 🙏🏼

Release Notes:

- Fixed an issue where WSL terminals could not be splitted

---------

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
This commit is contained in:
Marco Mihai Condrache
2025-10-06 13:18:27 +00:00
committed by GitHub
parent 93cd10aaa8
commit 5263f51432
4 changed files with 33 additions and 28 deletions
+29 -20
View File
@@ -404,31 +404,40 @@ impl Project {
&mut self,
terminal: &Entity<Terminal>,
cx: &mut Context<'_, Project>,
cwd: impl FnOnce() -> Option<PathBuf>,
cwd: Option<PathBuf>,
) -> Result<Entity<Terminal>> {
terminal.read(cx).clone_builder(cx, cwd).map(|builder| {
let terminal_handle = cx.new(|cx| builder.subscribe(cx));
let local_path = if self.is_via_remote_server() {
None
} else {
cwd
};
self.terminals
.local_handles
.push(terminal_handle.downgrade());
terminal
.read(cx)
.clone_builder(cx, local_path)
.map(|builder| {
let terminal_handle = cx.new(|cx| builder.subscribe(cx));
let id = terminal_handle.entity_id();
cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
let handles = &mut project.terminals.local_handles;
self.terminals
.local_handles
.push(terminal_handle.downgrade());
if let Some(index) = handles
.iter()
.position(|terminal| terminal.entity_id() == id)
{
handles.remove(index);
cx.notify();
}
let id = terminal_handle.entity_id();
cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
let handles = &mut project.terminals.local_handles;
if let Some(index) = handles
.iter()
.position(|terminal| terminal.entity_id() == id)
{
handles.remove(index);
cx.notify();
}
})
.detach();
terminal_handle
})
.detach();
terminal_handle
})
}
pub fn terminal_settings<'a>(
+2 -6
View File
@@ -2135,12 +2135,8 @@ impl Terminal {
self.vi_mode_enabled
}
pub fn clone_builder(
&self,
cx: &App,
cwd: impl FnOnce() -> Option<PathBuf>,
) -> Result<TerminalBuilder> {
let working_directory = self.working_directory().or_else(cwd);
pub fn clone_builder(&self, cx: &App, cwd: Option<PathBuf>) -> Result<TerminalBuilder> {
let working_directory = self.working_directory().or_else(|| cwd);
TerminalBuilder::new(
working_directory,
None,
+1 -1
View File
@@ -466,7 +466,7 @@ impl TerminalPanel {
Some(view) => Task::ready(project.clone_terminal(
&view.read(cx).terminal.clone(),
cx,
|| working_directory,
working_directory,
)),
None => project.create_terminal_shell(working_directory, cx),
})
+1 -1
View File
@@ -1225,7 +1225,7 @@ impl Item for TerminalView {
let cwd = project
.active_project_directory(cx)
.map(|it| it.to_path_buf());
project.clone_terminal(self.terminal(), cx, || cwd)
project.clone_terminal(self.terminal(), cx, cwd)
})
.ok()?
.log_err()?;