Garbage collection causes panic when accessing `ParsedDeclId` from `ParsedDeclEngine`
Today I noticed a panic when using the language server. It only seemed to happen very rarely so I wrote the below test.
Also, running the test with a single thread like below seemed to trigger the error more frequently.
cargo test did_change_stress_test_random -- --nocapture --test-threads=1
#[tokio::test]
#[allow(dead_code)]
async fn did_change_stress_test_random() {
set_panic_hook();
let (mut service, _) = LspService::build(ServerState::new)
.custom_method("sway/metrics", ServerState::metrics)
.finish();
let bench_dir = sway_workspace_dir().join("sway-lsp/tests/fixtures/benchmark");
let uri = init_and_open(&mut service, bench_dir.join("src/main.sw")).await;
let times = 40000;
for version in 0..times {
eprintln!("version: {}", version);
let _ = lsp::did_change_request(&mut service, &uri, version + 1).await;
if version == 0 {
service.inner().wait_for_parsing().await;
}
let metrics = lsp::metrics_request(&mut service, &uri).await;
for (path, metrics) in metrics {
if path.contains("sway-lib-core") || path.contains("sway-lib-std") {
assert!(metrics.reused_modules >= 1);
}
}
// wait for a random amount of time between 1-30ms
let wait_time = rand::random::<u64>() % 30 + 1;
tokio::time::sleep(tokio::time::Duration::from_millis(wait_time)).await;
// there is a 10% chance that a longer 300-1000ms wait will be added
if rand::random::<u64>() % 10 < 1 {
let wait_time = rand::random::<u64>() % 700 + 300;
tokio::time::sleep(tokio::time::Duration::from_millis(wait_time)).await;
}
}
shutdown_and_exit(&mut service).await;
}
fn set_panic_hook() {
std::env::set_var("RUST_BACKTRACE", "1");
let default_panic = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
eprintln!("PANIC!!!!!!!!!!!!!!!");
// Print the panic message
default_panic(panic_info);
eprintln!("exiting");
std::process::exit(1);
}));
}
And below is the output that caught the panic with the backtrace. It seems that in this instance it took 3243 didChange events for the ParsedDeclEngine to not contain an assumed valid ParsedDeclId for the let struct_decl = ctx.engines.pe().get_struct(self); to work.
I don't understand why calling GC the thousands of times before hand didn't lead to this ParsedDeclId not being removed. @tritao do you have any suggestions on what might be happening here? I have a branch here if you want to try recreating locally.
Garbage collection complete: version 3243
Starting compilation
Finished compilation
Starting traversal
PANIC!!!!!!!!!!!!!!!
PANIC!!!!!!!!!!!!!!!
PANIC!!!!!!!!!!!!!!!
PANIC!!!!!!!!!!!!!!!
thread 'thread 'PANIC!!!!!!!!!!!!!!!
<unnamed><unnamed>' panicked at thread 'thread 'sway-core/src/concurrent_slab.rs' panicked at <unnamed><unnamed>:sway-core/src/concurrent_slab.rs90:PANIC!!!!!!!!!!!!!!!
90thread '<unnamed>' panicked at sway-core/src/concurrent_slab.rs:90:thread '14' panicked at <unnamed>:
sway-core/src/concurrent_slab.rsPANIC!!!!!!!!!!!!!!!
' panicked at ::no entry found for keythread '
90<unnamed>::14:
sway-core/src/concurrent_slab.rsno entry found for key:
' panicked at sway-core/src/concurrent_slab.rsPANIC!!!!!!!!!!!!!!!
90:14:thread '14:
no entry found for key
90<unnamed>:' panicked at sway-core/src/concurrent_slab.rs14:
14no entry found for key:
:no entry found for key90
:' panicked at PANIC!!!!!!!!!!!!!!!
stack backtrace:
:
thread '<unnamed>' panicked at 14sway-core/src/concurrent_slab.rs:
PANIC!!!!!!!!!!!!!!!
thread '<unnamed>:' panicked at sway-core/src/concurrent_slab.rs90no entry found for keysway-core/src/concurrent_slab.rsno entry found for key:
90:14:
no entry found for key:
:90:14:
no entry found for key
14:
no entry found for key
version: 3243
version: 3244
version: 3245
version: 3246
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::panicking::panic_display
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:168:5
3: core::panicking::panic_str
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:152:5
4: core::option::expect_failed
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/option.rs:1988:5
5: core::option::Option<T>::expect
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/option.rs:898:21
6: <std::collections::hash::map::HashMap<K,V,S> as core::ops::index::Index<&Q>>::index
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/collections/hash/map.rs:1341:23
7: sway_core::concurrent_slab::ConcurrentSlab<T>::get
at /Users/joshuabatty/Documents/rust/fuel/sway/sway-core/src/concurrent_slab.rs:90:14
8: <sway_core::decl_engine::parsed_engine::ParsedDeclEngine as sway_core::decl_engine::parsed_engine::ParsedDeclEngineGet<sway_core::decl_engine::parsed_id::ParsedDeclId<sway_core::language::parsed::declaration::function::FunctionDeclaration>,sway_core::language::parsed::declaration::function::FunctionDeclaration>>::get
at /Users/joshuabatty/Documents/rust/fuel/sway/sway-core/src/decl_engine/parsed_engine.rs:59:17
9: sway_core::decl_engine::parsed_engine::ParsedDeclEngine::get_function
at /Users/joshuabatty/Documents/rust/fuel/sway/sway-core/src/decl_engine/parsed_engine.rs:185:9
10: sway_lsp::traverse::parsed_tree::<impl sway_lsp::traverse::Parse for sway_core::decl_engine::parsed_id::ParsedDeclId<sway_core::language::parsed::declaration::function::FunctionDeclaration>>::parse
at ./src/traverse/parsed_tree.rs:734:23
11: sway_lsp::traverse::parsed_tree::<impl sway_lsp::traverse::Parse for sway_core::language::parsed::declaration::Declaration>::parse
at ./src/traverse/parsed_tree.rs:124:58
12: sway_lsp::traverse::parsed_tree::<impl sway_lsp::traverse::Parse for sway_core::language::parsed::AstNode>::parse
at ./src/traverse/parsed_tree.rs:108:57
13: sway_lsp::traverse::parsed_tree::ParsedTree::traverse_node
at ./src/traverse/parsed_tree.rs:53:9
14: sway_lsp::core::session::traverse::{{closure}}
at ./src/core/session.rs:415:59
15: sway_lsp::core::session::parse_ast_to_tokens::{{closure}}
at ./src/core/session.rs:488:35
16: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &F>::call_mut
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/ops/function.rs:272:13
17: <core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::for_each
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/slice/iter/macros.rs:254:21
18: <rayon::iter::for_each::ForEachConsumer<F> as rayon::iter::plumbing::Folder<T>>::consume_iter
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/for_each.rs:55:9
19: rayon::iter::plumbing::Producer::fold_with
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:110:9
20: rayon::iter::plumbing::bridge_producer_consumer::helper
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:438:13
21: rayon::iter::plumbing::bridge_producer_consumer::helper::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:418:21
22: rayon_core::join::join_context::call_a::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:124:17
23: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panic/unwind_safe.rs:271:9
24: std::panicking::try::do_call
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:504:40
25: ___rust_try
26: std::panicking::try
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:468:19
27: std::panic::catch_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panic.rs:142:14
28: rayon_core::unwind::halt_unwinding
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/unwind.rs:17:5
29: rayon_core::join::join_context::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:142:24
30: rayon_core::registry::in_worker
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:950:13
31: rayon_core::join::join_context
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:132:5
32: rayon::iter::plumbing::bridge_producer_consumer::helper
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:416:47
33: rayon::iter::plumbing::bridge_producer_consumer::helper::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:418:21
34: rayon_core::join::join_context::call_a::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:124:17
35: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panic/unwind_safe.rs:271:9
36: std::panicking::try::do_call
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:504:40
37: ___rust_try
38: std::panicking::try
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:468:19
39: std::panic::catch_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panic.rs:142:14
40: rayon_core::unwind::halt_unwinding
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/unwind.rs:17:5
41: rayon_core::join::join_context::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:142:24
42: rayon_core::registry::in_worker
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:950:13
43: rayon_core::join::join_context
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:132:5
44: rayon::iter::plumbing::bridge_producer_consumer::helper
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:416:47
45: rayon::iter::plumbing::bridge_producer_consumer::helper::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.8.0/src/iter/plumbing/mod.rs:427:21
46: rayon_core::join::join_context::call_b::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/join/mod.rs:129:25
47: rayon_core::job::JobResult<T>::call::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/job.rs:218:41
48: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panic/unwind_safe.rs:271:9
49: std::panicking::try::do_call
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:504:40
50: ___rust_try
51: std::panicking::try
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:468:19
52: std::panic::catch_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panic.rs:142:14
53: rayon_core::unwind::halt_unwinding
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/unwind.rs:17:5
54: rayon_core::job::JobResult<T>::call
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/job.rs:218:15
55: <rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/job.rs:120:32
56: rayon_core::job::JobRef::execute
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/job.rs:64:9
57: rayon_core::registry::WorkerThread::execute
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:859:9
58: rayon_core::registry::WorkerThread::wait_until_cold
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:793:21
59: rayon_core::registry::WorkerThread::wait_until
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:768:13
60: rayon_core::registry::WorkerThread::wait_until_out_of_work
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:817:9
61: rayon_core::registry::main_loop
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:922:5
62: rayon_core::registry::ThreadBuilder::run
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:52:18
63: <rayon_core::registry::DefaultSpawn as rayon_core::registry::ThreadSpawn>::spawn::{{closure}}
at /Users/joshuabatty/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rayon-core-1.12.0/src/registry.rs:97:20
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
exiting
stack backtrace:
error: test failed, to rerun pass `--test lib`
请问这个是不是还没有实现?
"This issue has been inactive for a prolonged period and will be closed automatically in 3 days." "该问题已长时间处于闲置状态,3 天后将自动关闭。"