Skip to content

Serialize SharpWavtool cache file reads per path - #2442

Merged
stakira merged 2 commits into
masterfrom
fix-sharpwavtool-cache-lock
Sep 24, 2026
Merged

stakira merged 2 commits into
masterfrom
fix-sharpwavtool-cache-lock

Conversation

@stakira

@stakira stakira commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Fixes the 'file is being used by another process' IOException from SharpWavtool.Concatenate (see error report, OpenUtau 0.1.570.3).

Same fix pattern as 9138af6 (WorldlineRenderer): guard the cache read with the per-path lock. Here it's simpler because the write side (ClassicRenderer.RenderInternal) already runs under the shared Renderers.GetCacheLock(outputFile) — the read just needs to take the same lock object, which serializes it against concurrent resample writes and against other phrases reading the same res-*.wav (NAudio opens with FileShare.None, so even read/read conflicts).

Notes:

  • ExeWavtool/UnixWavtool need no change: their C# side only reads the per-phrase temp file, and their resample writes are already locked.
  • Residual (out of scope): the File.Exists check before resampling in RenderInternal is outside the lock and not re-checked inside, so two threads can still double-resample the same phone (wasteful, not a crash); the direct-phone read of the voicebank source file has the same read/read exposure.

@stakira
stakira requested review from a team and a lite review from Copilot September 24, 2026 05:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved review comments remain, and the cache reads use the existing shared locking scheme.

Review effort: Lite
Findings: None

What changed in this PR

This pull request serializes SharpWavtool cache reads using the existing per-path locks to prevent concurrent WAV file-access failures.

Changes:

  • Locks cached WAV existence checks and reads with Renderers.GetCacheLock.
  • Aligns cache reads with existing resampler write locking.
File Description
OpenUtau.Core/​Classic/​SharpWavtool.cs Adds per-cache-path synchronization around resampled audio reads.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Two phrases with identical phones hash to the same res-*.wav cache
path, and RenderInternal() can run concurrently. The resample write
already runs under the per-path lock from Renderers.GetCacheLock(),
but the read in SharpWavtool.Concatenate() did not, so a concurrent
read could race a still-open write (or another reader) and throw
"file is being used by another process". Guard the read with the
same per-path lock, like 9138af6 did for WorldlineRenderer.
The local cacheFileLocks dictionary is a leftover from before
Renderers.GetCacheLock() existed. Its wdl-* paths do not collide with
paths locked elsewhere, so the shared per-path map is a drop-in
replacement and removes the duplicate.
@stakira
stakira force-pushed the fix-sharpwavtool-cache-lock branch from 4ad618c to f1ecc24 Compare September 24, 2026 06:11
@stakira
stakira merged commit 5d17f14 into master Sep 24, 2026
3 checks passed
@stakira
stakira deleted the fix-sharpwavtool-cache-lock branch September 24, 2026 10:19
keirokeer added a commit to keirokeer/OpenUtau-lunai that referenced this pull request Sep 25, 2026
Guard concurrent SharpWavtool reads with Renderers.GetCacheLock; drop local WorldlineRenderer lock map.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants