mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-11-25 13:23:44 +00:00
fix: always send compiled interrupt to main thread (#2001)
We have to always inform the main thread about the compilation. If such interrupt is not sent, the main thread will be stalled forever.
This commit is contained in:
parent
4c242c54e8
commit
bc09736cc6
1 changed files with 43 additions and 6 deletions
|
|
@ -23,6 +23,7 @@ use reflexo_typst::{diag::print_diagnostics, TypstDocument};
|
|||
use serde::{Deserialize, Serialize};
|
||||
pub use tinymist_project::*;
|
||||
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::{num::NonZeroUsize, sync::Arc};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
|
@ -239,7 +240,7 @@ pub struct ProjectInsStateExt {
|
|||
pub notified_revision: usize,
|
||||
pub pending_reasons: CompileSignal,
|
||||
pub emitted_reasons: CompileSignal,
|
||||
pub is_compiling: bool,
|
||||
pub compiling_since: Option<tinymist_std::time::Time>,
|
||||
pub last_compilation: Option<LspCompiledArtifact>,
|
||||
}
|
||||
|
||||
|
|
@ -252,13 +253,14 @@ impl ProjectInsStateExt {
|
|||
handler: &dyn CompileHandler<LspCompilerFeat, ProjectInsStateExt>,
|
||||
compilation: &LspCompiledArtifact,
|
||||
) {
|
||||
self.compiling_since = None;
|
||||
|
||||
let rev = compilation.world().revision().get();
|
||||
if self.notified_revision >= rev {
|
||||
return;
|
||||
}
|
||||
self.notified_revision = rev;
|
||||
|
||||
self.is_compiling = false;
|
||||
self.last_compilation = Some(compilation.clone());
|
||||
|
||||
self.emit_pending_reasons(revision, handler);
|
||||
|
|
@ -325,6 +327,11 @@ impl ProjectState {
|
|||
if let Some(proj) = proj {
|
||||
proj.ext
|
||||
.compiled(&proj.verse.revision, proj.handler.as_ref(), compiled);
|
||||
} else {
|
||||
log::info!(
|
||||
"Project({:?}): process compiled not found",
|
||||
compiled.snap.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +524,28 @@ impl CompileHandler<LspCompilerFeat, ProjectInsStateExt> for CompileHandlerImpl
|
|||
fn on_any_compile_reason(&self, c: &mut LspProjectCompiler) {
|
||||
let instances_mut = std::iter::once(&mut c.primary).chain(c.dedicates.iter_mut());
|
||||
for s in instances_mut {
|
||||
if s.ext.is_compiling {
|
||||
let id = &s.id;
|
||||
|
||||
if let Some(compiling_since) = &s.ext.compiling_since {
|
||||
static CHECK_COMPILE_TIMEOUT: AtomicUsize = AtomicUsize::new(0);
|
||||
let check_stalled = (CHECK_COMPILE_TIMEOUT
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
||||
& 0xFF)
|
||||
== 0;
|
||||
|
||||
if check_stalled {
|
||||
let since = (tinymist_std::time::Time::now().duration_since(*compiling_since))
|
||||
.unwrap_or_default();
|
||||
|
||||
if since.as_secs() > 60 {
|
||||
log::warn!(
|
||||
"Project: {id:?} is compiling for more than 60 seconds, since: {since:?}, \
|
||||
pending reasons: {:?}",
|
||||
s.ext.pending_reasons
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -530,13 +558,19 @@ impl CompileHandler<LspCompilerFeat, ProjectInsStateExt> for CompileHandlerImpl
|
|||
};
|
||||
|
||||
let is_vfs_sub = reason.any() && !reason.exclude(VFS_SUB).any();
|
||||
let id = &s.id;
|
||||
|
||||
if is_vfs_sub
|
||||
&& 'vfs_is_clean: {
|
||||
let Some(compilation) = &s.ext.last_compilation else {
|
||||
break 'vfs_is_clean false;
|
||||
};
|
||||
if compilation.world().entry_state() != s.verse.entry_state() {
|
||||
log::info!("Project: updated regardless of vfs for {id:?} due to entry state change, world: {:?} v.s. verse: {:?}",
|
||||
compilation.world().entry_state(),
|
||||
s.verse.entry_state(),
|
||||
);
|
||||
break 'vfs_is_clean false;
|
||||
}
|
||||
|
||||
let last_rev = compilation.world().vfs().revision();
|
||||
let deps = compilation.depended_files().clone();
|
||||
|
|
@ -567,7 +601,7 @@ impl CompileHandler<LspCompilerFeat, ProjectInsStateExt> for CompileHandlerImpl
|
|||
let Some(compile_fn) = s.may_compile(&c.handler) else {
|
||||
continue;
|
||||
};
|
||||
s.ext.is_compiling = true;
|
||||
s.ext.compiling_since = Some(tinymist_std::time::Time::now());
|
||||
rayon::spawn(move || {
|
||||
compile_fn();
|
||||
});
|
||||
|
|
@ -623,6 +657,10 @@ impl CompileHandler<LspCompilerFeat, ProjectInsStateExt> for CompileHandlerImpl
|
|||
}
|
||||
|
||||
fn notify_compile(&self, art: &LspCompiledArtifact) {
|
||||
// NOTE: we have to inform the main thread about the compilation. If such
|
||||
// interrupt is not sent, the main thread will be stalled forever.
|
||||
self.client.interrupt(LspInterrupt::Compiled(art.clone()));
|
||||
|
||||
{
|
||||
let mut n_revs = self.notified_revision.lock();
|
||||
let (n_rev, n_signal) = n_revs.entry(art.id().clone()).or_default();
|
||||
|
|
@ -664,7 +702,6 @@ impl CompileHandler<LspCompilerFeat, ProjectInsStateExt> for CompileHandlerImpl
|
|||
.log_error("failed to print diagnostics");
|
||||
}
|
||||
|
||||
self.client.interrupt(LspInterrupt::Compiled(art.clone()));
|
||||
self.export.signal(art, &self.client);
|
||||
|
||||
#[cfg(feature = "preview")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue