Skip to content

Commit eea429a

Browse files
authored
fix(core): remove blocking to avoid deadlock for multi compiler (#9587)
* fix(core): remove blocking to avoid deadlock for multi compiler * chore: fix clippy * chore: add safety comment * chore: skip test
1 parent 9fdb06f commit eea429a

File tree

5 files changed

+67
-53
lines changed

5 files changed

+67
-53
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101
target: wasm32-wasip1-threads
102102
profile: "ci"
103103
runner: ${{ needs.get-runner-labels.outputs.LINUX_RUNNER_LABELS }}
104-
skipable: ${{ needs.check-changed.outputs.changed != 'true' }}
104+
skipable: true
105105
full-install: false
106106
test: false
107107

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rspack_core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ version = "0.2.0"
88
[dependencies]
99
anymap = { workspace = true }
1010
async-recursion = { workspace = true }
11+
async-scoped = { workspace = true }
1112
async-trait = { workspace = true }
1213
bitflags = { workspace = true }
1314
cow-utils = { workspace = true }

crates/rspack_core/src/compiler/compilation.rs

+37-27
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
},
99
};
1010

11+
use async_scoped::TokioScope;
1112
use dashmap::DashSet;
1213
use indexmap::{IndexMap, IndexSet};
1314
use itertools::Itertools;
@@ -19,9 +20,9 @@ use rspack_cacheable::{
1920
use rspack_collections::{
2021
DatabaseItem, Identifiable, IdentifierDashMap, IdentifierMap, IdentifierSet, UkeyMap, UkeySet,
2122
};
23+
use rspack_error::error;
2224
use rspack_error::{
23-
error, miette::diagnostic, Diagnostic, DiagnosticExt, InternalError, Result, RspackSeverity,
24-
Severity,
25+
miette::diagnostic, Diagnostic, DiagnosticExt, InternalError, Result, RspackSeverity, Severity,
2526
};
2627
use rspack_fs::{IntermediateFileSystem, ReadableFileSystem, WritableFileSystem};
2728
use rspack_futures::FuturesResults;
@@ -1054,31 +1055,40 @@ impl Compilation {
10541055
} else {
10551056
self.chunk_by_ukey.keys().copied().collect()
10561057
};
1057-
let chunk_render_results = chunks
1058-
.iter()
1059-
.map(|chunk| async {
1060-
let mut manifests = Vec::new();
1061-
let mut diagnostics = Vec::new();
1062-
plugin_driver
1063-
.compilation_hooks
1064-
.render_manifest
1065-
.call(self, chunk, &mut manifests, &mut diagnostics)
1066-
.await?;
1067-
1068-
Ok((
1069-
*chunk,
1070-
ChunkRenderResult {
1071-
manifests,
1072-
diagnostics,
1073-
},
1074-
))
1075-
})
1076-
.collect::<FuturesResults<Result<_>>>();
1077-
let chunk_render_results = chunk_render_results
1078-
.into_inner()
1079-
.into_iter()
1080-
.collect::<Result<UkeyMap<_, _>>>()?;
1081-
1058+
// SAFETY: await immediately and trust caller to poll future entirely
1059+
let (_, results) = unsafe {
1060+
async_scoped::TokioScope::scope_and_collect(
1061+
|s: &mut TokioScope<'_, Result<(ChunkUkey, ChunkRenderResult)>>| {
1062+
chunks.iter().for_each(|chunk| {
1063+
s.spawn(async {
1064+
let mut manifests = Vec::new();
1065+
let mut diagnostics = Vec::new();
1066+
plugin_driver
1067+
.compilation_hooks
1068+
.render_manifest
1069+
.call(self, chunk, &mut manifests, &mut diagnostics)
1070+
.await?;
1071+
1072+
rspack_error::Result::Ok((
1073+
*chunk,
1074+
ChunkRenderResult {
1075+
manifests,
1076+
diagnostics,
1077+
},
1078+
))
1079+
});
1080+
})
1081+
},
1082+
)
1083+
}
1084+
.await;
1085+
let mut chunk_render_results: UkeyMap<ChunkUkey, ChunkRenderResult> = Default::default();
1086+
for result in results {
1087+
let item: std::result::Result<(ChunkUkey, ChunkRenderResult), _> =
1088+
result.map_err(rspack_error::miette::Error::from_err)?;
1089+
let (key, value) = item?;
1090+
chunk_render_results.insert(key, value);
1091+
}
10821092
let chunk_ukey_and_manifest = if mutations.is_some() {
10831093
self.chunk_render_artifact.extend(chunk_render_results);
10841094
self.chunk_render_artifact.clone()

crates/rspack_core/src/compiler/mod.rs

+27-25
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod rebuild;
55
use std::sync::atomic::AtomicU32;
66
use std::sync::Arc;
77

8+
use async_scoped::TokioScope;
89
use rspack_error::Result;
910
use rspack_fs::{IntermediateFileSystem, NativeFileSystem, ReadableFileSystem, WritableFileSystem};
1011
use rspack_futures::FuturesResults;
@@ -343,36 +344,37 @@ impl Compiler {
343344
.await?;
344345

345346
let mut new_emitted_asset_versions = HashMap::default();
346-
let results = self
347-
.compilation
348-
.assets()
349-
.iter()
350-
.filter_map(|(filename, asset)| {
351-
// collect version info to new_emitted_asset_versions
352-
if self
353-
.options
354-
.experiments
355-
.incremental
356-
.contains(IncrementalPasses::EMIT_ASSETS)
357-
{
358-
new_emitted_asset_versions.insert(filename.to_string(), asset.info.version.clone());
359-
}
347+
// SAFETY: await immediately and trust caller to poll future entirely
348+
let _ = unsafe {
349+
TokioScope::scope_and_collect(|s| {
350+
self
351+
.compilation
352+
.assets()
353+
.iter()
354+
.for_each(|(filename, asset)| {
355+
// collect version info to new_emitted_asset_versions
356+
if self
357+
.options
358+
.experiments
359+
.incremental
360+
.contains(IncrementalPasses::EMIT_ASSETS)
361+
{
362+
new_emitted_asset_versions.insert(filename.to_string(), asset.info.version.clone());
363+
}
360364

361-
if let Some(old_version) = self.emitted_asset_versions.get(filename) {
362-
if old_version.as_str() == asset.info.version && !old_version.is_empty() {
363-
return None;
364-
}
365-
}
365+
if let Some(old_version) = self.emitted_asset_versions.get(filename) {
366+
if old_version.as_str() == asset.info.version && !old_version.is_empty() {
367+
return;
368+
}
369+
}
366370

367-
Some(self.emit_asset(&self.options.output.path, filename, asset))
371+
s.spawn(self.emit_asset(&self.options.output.path, filename, asset));
372+
})
368373
})
369-
.collect::<FuturesResults<_>>();
374+
}
375+
.await;
370376

371377
self.emitted_asset_versions = new_emitted_asset_versions;
372-
// return first error
373-
for item in results.into_inner() {
374-
item?;
375-
}
376378

377379
self
378380
.plugin_driver

0 commit comments

Comments
 (0)