Asset hot reload can deadlock when the Asset Processor reprocesses an asset the asset server is reloading
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 18/100
Direzione di ricerca
The deadlock involves get_meta_loader_and_reader in crates/bevy_asset/src/server/mod.rs and the gated readers in crates/bevy_asset/src/io/processor_gated.rs, where read and read_meta each take a read guard on the file_transaction_lock. The processor's write_arc().await in crates/bevy_asset/src/processor/mod.rs is the writer that blocks. Start by reproducing the race with a test that changes a source file right after its first load, then check whether the second read guard can be avoided. Done means the asset reloads reliably in that timing window without the 1 s workaround.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Bevy version
0.20.0, and the code in question is unchanged on main (ae6152152d).
Relevant system information
Windows 11, Rust stable. The race is in platform-independent code.
What you did
An App with AssetPlugin { mode: AssetMode::Processed, use_asset_processor_override: Some(true), watch_for_changes_override: Some(true), .. }, so the Asset Processor runs inside the app and both the source folder and the processed folder are watched. Load an asset, then change its source file shortly after the first processing has finished.
What went wrong
About 2% of the time the changed asset never reloads, nothing is logged, and that asset never reloads again until restart. Other assets keep hot reloading.
It is a deadlock on that asset's file_transaction_lock, an async_lock::RwLock. async_lock holds new readers back while a writer waits:
- The asset server reloads the asset.
get_meta_loader_and_readerkeeps the meta reader alive while it opens the asset reader (L1477), so that the asset reader can "take over" the lock. ThroughProcessorGatedReader, each of the two readers takes its own read guard (read,read_meta). So the server holds one read guard and asks for a second one. - In between, the processor starts processing the same asset again and waits for the write guard (
write_arc().await). - The second read waits behind the waiting writer, and the writer waits for the first read guard, which is only dropped after the second read. Neither proceeds.
What makes the two meet: about 300 ms (the debounce) after the first processing, the processed folder's watcher reports every file the processor wrote, and the asset server reloads them. A source change in that window is reported by the source watcher at about the same instant, so the processor reprocesses the file while the server reloads it.
A trace (bevy_asset at TRACE) of a stuck run shows, for the stuck asset, all at the same millisecond:
DEBUG bevy_asset::processor: Processing graphs\restart.graph.ron
TRACE bevy_asset::io::processor_gated: Processing finished with Processed, reading meta for graphs/restart.graph.ron
TRACE bevy_asset::io::processor_gated: Processing finished with graphs/restart.graph.ron, reading Processed
After that there is no Finished processing, Skipping processing or Reloaded line for that asset, while the other assets reload normally. The second processor_gated line is logged just before get_transaction_lock, where the read blocks.
Additional information
- How often: with a test that changes a source right after its first load, 9 failures in 400 runs. With the app updated for 1 s after the load before the change (past the debounce), 0 in 400. We use that wait as a workaround in our tests.
- We don't have a standalone minimal repro yet. The setup above is the whole recipe; the timing window is narrow.
- Possible fixes: let the asset reader reuse the meta reader's guard instead of taking a second one (for example by passing the guard through, or by taking one guard per load in the gated reader), or take both readers under a single guard. Any change that avoids a recursive read acquisition on a lock that prefers writers would do.
- Lingua principale
- Rust
- Stelle
- 49.7k
- Fork
- 5k
- Merge medio
- 3g 19h
- PR unite (30g)
- 134
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di bevyengine/bevy
-
C-Bug S-Needs-Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
bevyengine/bevy#26536 ·
I maintainer di solito rispondono entro 2 giorni
-
Placeholder has no defaultForse già presa Una pull request collegata a questa issue è aperta o già unita. ApertaC-Feature S-Needs-Triage
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
bevyengine/bevy#26532 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
C-Feature S-Needs-Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
bevyengine/bevy#26500 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
C-Feature S-Needs-Triage
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 68/100
bevyengine/bevy#26499 ·
I maintainer di solito rispondono entro 2 giorni
-
`compute_histogram` in auto exposure writes past the end of the 64-bin histogramForse già presa @dev-matru l’ha presa 3 giorni fa. ApertaA-Rendering C-Bug D-Straightforward S-Ready-For-Implementation X-Uncontroversial
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
bevyengine/bevy#26479 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di bevyengine/bevy
Issue simili
-
remove the use of `forget`Apertagood first issue help wanted
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
swc-project/swc-ai-issues#907 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
-
area:helper kind:bug priority:p3 ready
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
bug UI
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
wardian-app/Wardian#1746 ·
I maintainer di solito rispondono entro 1 giorno