Skip to content

Fix concurrent HashSet modification when serializing archive meta#618

Merged
haga-rak merged 1 commit into
mainfrom
fix/archive-meta-tags-race
Apr 11, 2026
Merged

Fix concurrent HashSet modification when serializing archive meta#618
haga-rak merged 1 commit into
mainfrom
fix/archive-meta-tags-race

Conversation

@haga-rak
Copy link
Copy Markdown
Owner

@haga-rak haga-rak commented Apr 11, 2026

Summary

DirectoryArchiveWriter guarded _archiveMetaInformation.Tags with two different locks: UpdateMeta and UpdateTags locked on the path string, while Update(ExchangeInfo) locked on the meta object itself. That meant two threads could be inside the tag code at the same time, one adding to the HashSet while the other was enumerating it through JsonSerializer.Serialize, which throws "Collection was modified; enumeration operation may not execute".

The issue shows up more often when UseDnsOverHttpsAction is enabled because every DoH query becomes its own captured exchange, roughly doubling the concurrent write traffic through the archive writer.

This PR routes every access through a single _metaLock and keeps the UpdateMeta(true) call inside the lock so the Add and the serialize never interleave. The lock on an interned string was also a latent issue and is gone.

UpdateMeta, UpdateTags and Update(ExchangeInfo) all touched
_archiveMetaInformation.Tags but guarded it with two different locks
(one on the path string, another on the meta object itself), so a
thread adding a tag could race a thread serializing the meta file and
trip "Collection was modified" inside JsonSerializer. Route every
access through a single _metaLock and keep UpdateMeta inside the lock.
@haga-rak haga-rak merged commit 512bec4 into main Apr 11, 2026
3 of 4 checks passed
@haga-rak haga-rak added the bug Something isn't working label Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant