debugger: Fix restarting terminated child sessions (#29173)

This fixes a bug where terminated child session failed to restart
because they were using the wrong configuration/binary to start a new
session

Release Notes:

- N/A
This commit is contained in:
Anthony Eid 2025-04-21 14:25:38 -04:00 committed by GitHub
parent 0f3ac38332
commit e8fe0eb2e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 40 deletions

View file

@ -902,15 +902,6 @@ fn create_new_session(
this.shutdown_session(session_id, cx).detach_and_log_err(cx);
}
SessionStateEvent::Restart => {
let Some((config, binary)) = session.read_with(cx, |session, _| {
session
.configuration()
.map(|config| (config, session.binary().clone()))
}) else {
log::error!("Failed to get debug config from session");
return;
};
let mut curr_session = session;
while let Some(parent_id) = curr_session.read(cx).parent_id() {
if let Some(parent_session) = this.sessions.get(&parent_id).cloned() {
@ -921,6 +912,15 @@ fn create_new_session(
}
}
let Some((config, binary)) = curr_session.read_with(cx, |session, _| {
session
.configuration()
.map(|config| (config, session.root_binary().clone()))
}) else {
log::error!("Failed to get debug config from session");
return;
};
let session_id = curr_session.read(cx).session_id();
let task = curr_session.update(cx, |session, cx| session.shutdown(cx));
@ -931,7 +931,13 @@ fn create_new_session(
this.update(cx, |this, cx| {
this.sessions.remove(&session_id);
this.new_session(binary, config, worktree, None, cx)
this.new_session(
binary.as_ref().clone(),
config,
worktree,
None,
cx,
)
})?
.1
.await?;

View file

@ -164,6 +164,7 @@ pub struct LocalMode {
client: Arc<DebugAdapterClient>,
definition: DebugTaskDefinition,
binary: DebugAdapterBinary,
root_binary: Option<Arc<DebugAdapterBinary>>,
pub(crate) breakpoint_store: Entity<BreakpointStore>,
tmp_breakpoint: Option<SourceBreakpoint>,
worktree: WeakEntity<Worktree>,
@ -194,36 +195,18 @@ impl LocalMode {
binary: DebugAdapterBinary,
messages_tx: futures::channel::mpsc::UnboundedSender<Message>,
cx: AsyncApp,
) -> Task<Result<Self>> {
Self::new_inner(
session_id,
parent_session,
breakpoint_store,
worktree,
config,
binary,
messages_tx,
async |_, _| {},
cx,
)
}
fn new_inner(
session_id: SessionId,
parent_session: Option<Entity<Session>>,
breakpoint_store: Entity<BreakpointStore>,
worktree: WeakEntity<Worktree>,
config: DebugTaskDefinition,
binary: DebugAdapterBinary,
messages_tx: futures::channel::mpsc::UnboundedSender<Message>,
on_initialized: impl AsyncFnOnce(&mut LocalMode, AsyncApp) + 'static,
cx: AsyncApp,
) -> Task<Result<Self>> {
cx.spawn(async move |cx| {
let message_handler = Box::new(move |message| {
messages_tx.unbounded_send(message).ok();
});
let root_binary = if let Some(parent_session) = parent_session.as_ref() {
Some(parent_session.read_with(cx, |session, _| session.root_binary().clone())?)
} else {
None
};
let client = Arc::new(
if let Some(client) = parent_session
.and_then(|session| cx.update(|cx| session.read(cx).adapter_client()).ok())
@ -244,18 +227,15 @@ impl LocalMode {
},
);
let mut session = Self {
Ok(Self {
client,
breakpoint_store,
worktree,
tmp_breakpoint: None,
definition: config,
root_binary,
binary,
};
on_initialized(&mut session, cx.clone()).await;
Ok(session)
})
})
}
@ -840,6 +820,16 @@ impl Session {
&self.capabilities
}
pub(crate) fn root_binary(&self) -> Arc<DebugAdapterBinary> {
let Mode::Local(local_mode) = &self.mode else {
panic!("Session is not local");
};
local_mode
.root_binary
.clone()
.unwrap_or_else(|| Arc::new(local_mode.binary.clone()))
}
pub fn binary(&self) -> &DebugAdapterBinary {
let Mode::Local(local_mode) = &self.mode else {
panic!("Session is not local");