Skip to content

Commit

Permalink
fix(lsp): fix deadlocks, use one big mutex (denoland#9271)
Browse files Browse the repository at this point in the history
The LSP code had numerous places where competing threads could take out
out locks in different orders, making it very prone to deadlocks.
This commit sidesteps the entire issue by switching to a single lock.

The above is a little white lie: the Sources struct still uses a mutex
internally to avoid having to boil the ocean (because being honest about
what it does involves changing all its methods to `&mut self` but that
ripples out extensively...) I'll save that one for another day.
  • Loading branch information
bnoordhuis committed Jan 26, 2021
1 parent 2823c02 commit 2828690
Show file tree
Hide file tree
Showing 4 changed files with 342 additions and 211 deletions.
9 changes: 2 additions & 7 deletions cli/lsp/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use super::tsc;
use crate::diagnostics;
use crate::media_type::MediaType;

use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::serde_json;
use deno_core::ModuleSpecifier;
Expand Down Expand Up @@ -265,17 +264,13 @@ pub async fn generate_ts_diagnostics(
}

pub async fn generate_dependency_diagnostics(
state_snapshot: StateSnapshot,
mut state_snapshot: StateSnapshot,
diagnostic_collection: DiagnosticCollection,
) -> Result<DiagnosticVec, AnyError> {
tokio::task::spawn_blocking(move || {
let mut diagnostics = Vec::new();

let mut sources = if let Ok(sources) = state_snapshot.sources.lock() {
sources
} else {
return Err(custom_error("Deadlock", "deadlock locking sources"));
};
let sources = &mut state_snapshot.sources;
for specifier in state_snapshot.documents.open_specifiers() {
let version = state_snapshot.documents.version(specifier);
let current_version = diagnostic_collection.get_version(specifier);
Expand Down
Loading

0 comments on commit 2828690

Please sign in to comment.