Fixed a hang when the cleanup code for an extension is too slow

This commit is contained in:
2026-01-20 15:24:34 +01:00
parent cb111a8d7b
commit 237b40ed2e
6 changed files with 274 additions and 270 deletions

View File

@@ -103,18 +103,24 @@ impl Expr {
}
impl Format for Expr {
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
return print_expr(self, c, Substack::Bottom).await;
return print_expr(self, c, Substack::Bottom, &[]).await;
}
}
async fn print_expr<'a>(
pub async fn print_expr<'a>(
expr: &'a Expr,
c: &'a (impl FmtCtx + ?Sized + 'a),
visited: Substack<'_, api::ExprTicket>,
id_only: &[api::ExprTicket],
) -> FmtUnit {
if visited.iter().any(|id| id == &expr.id()) {
return "CYCLIC_EXPR".to_string().into();
}
print_exprkind(&*expr.kind().read().await, c, visited.push(expr.id())).boxed_local().await
if id_only.iter().any(|id| id == &expr.id()) {
return format!("{:?}", expr.id()).into();
}
print_exprkind(&*expr.kind().read().await, c, visited.push(expr.id()), id_only)
.boxed_local()
.await
}
#[derive(Clone, Debug)]
@@ -138,13 +144,14 @@ impl ExprKind {
}
impl Format for ExprKind {
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
print_exprkind(self, c, Substack::Bottom).await
print_exprkind(self, c, Substack::Bottom, &[]).await
}
}
async fn print_exprkind<'a>(
ek: &ExprKind,
c: &'a (impl FmtCtx + ?Sized + 'a),
visited: Substack<'_, api::ExprTicket>,
id_only: &[api::ExprTicket],
) -> FmtUnit {
match &ek {
ExprKind::Arg => "Arg".to_string().into(),
@@ -156,10 +163,10 @@ async fn print_exprkind<'a>(
ExprKind::Call(f, x) => tl_cache!(Rc<Variants>: Rc::new(Variants::default()
.unbounded("{0b} {1l}")
.bounded("({0b} {1})")))
.units([print_expr(f, c, visited).await, print_expr(x, c, visited).await]),
.units([print_expr(f, c, visited, id_only).await, print_expr(x, c, visited, id_only).await]),
ExprKind::Identity(id) =>
tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("{{{0}}}"))).units([print_expr(
id, c, visited,
id, c, visited, id_only,
)
.boxed_local()
.await]),
@@ -167,14 +174,14 @@ async fn print_exprkind<'a>(
ExprKind::Lambda(None, body) => tl_cache!(Rc<Variants>: Rc::new(Variants::default()
// .unbounded("\\.{0l}")
.bounded("(\\.{0b})")))
.units([print_expr(body, c, visited).await]),
.units([print_expr(body, c, visited, id_only).await]),
ExprKind::Lambda(Some(path), body) => tl_cache!(Rc<Variants>: Rc::new(Variants::default()
// .unbounded("\\{0b}. {1l}")
.bounded("(\\{0b}. {1b})")))
.units([format!("{path}").into(), print_expr(body, c, visited).await]),
.units([format!("{path}").into(), print_expr(body, c, visited, id_only).await]),
ExprKind::Seq(l, r) =>
tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("[{0b}]{1l}")))
.units([print_expr(l, c, visited).await, print_expr(r, c, visited).await]),
.units([print_expr(l, c, visited, id_only).await, print_expr(r, c, visited, id_only).await]),
}
}

View File

@@ -102,11 +102,7 @@ impl Extension {
this.0.ctx.exprs.give_expr(target)
},
api::ExtHostNotif::ExprNotif(api::ExprNotif::Release(rel)) => {
if this.is_own_sys(rel.0).await {
this.0.ctx.exprs.take_expr(rel.1);
} else {
writeln!(log("warn"), "Not our system {:?}", rel.0).await
}
this.0.ctx.exprs.take_expr(rel.1);
},
api::ExtHostNotif::Log(api::Log { category, message }) =>
write!(log(&es(category).await), "{message}").await,
@@ -130,7 +126,7 @@ impl Extension {
// Atom printing and interning is never reported because it generates too much
// noise
if !matches!(req, api::ExtHostReq::ExtAtomPrint(_))
|| matches!(req, api::ExtHostReq::IntReq(_))
&& !matches!(req, api::ExtHostReq::IntReq(_))
{
writeln!(log("msg"), "Host received request {req:?}").await;
}
@@ -299,14 +295,6 @@ impl Extension {
pub fn ctx(&self) -> &Ctx { &self.0.ctx }
pub fn system_ctors(&self) -> impl Iterator<Item = &SystemCtor> { self.0.systems.iter() }
#[must_use]
pub async fn is_own_sys(&self, id: api::SysId) -> bool {
let Some(sys) = self.ctx().system_inst(id).await else {
writeln!(log("warn"), "Invalid system ID {id:?}").await;
return false;
};
Rc::ptr_eq(&self.0, &sys.ext().0)
}
#[must_use]
pub fn next_pars(&self) -> NonZeroU64 {
let mut next_pars = self.0.next_pars.borrow_mut();
*next_pars = next_pars.checked_add(1).unwrap_or(NonZeroU64::new(1).unwrap());