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); this.shutdown_session(session_id, cx).detach_and_log_err(cx);
} }
SessionStateEvent::Restart => { 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; let mut curr_session = session;
while let Some(parent_id) = curr_session.read(cx).parent_id() { while let Some(parent_id) = curr_session.read(cx).parent_id() {
if let Some(parent_session) = this.sessions.get(&parent_id).cloned() { 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 session_id = curr_session.read(cx).session_id();
let task = curr_session.update(cx, |session, cx| session.shutdown(cx)); 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.update(cx, |this, cx| {
this.sessions.remove(&session_id); 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 .1
.await?; .await?;

View file

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