Skip to content

Synchronize CanGetInstance with delegate creation - #616

Merged
seesharper merged 1 commit into
masterfrom
fix-concurrent-open-generic-enumerable
Sep 25, 2026
Merged

seesharper merged 1 commit into
masterfrom
fix-concurrent-open-generic-enumerable

Conversation

@seesharper

Copy link
Copy Markdown
Owner

Fixes #614

Problem

CreateDelegate holds lockObject while building emit methods, but CanGetInstance walks the same GetEmitMethod → CreateEmitMethodForUnknownService path without the lock. That path can register closed generic services, appending to the List<ServiceRegistration> / List<EmitMethodInfo> values in allRegistrations / allEmitters while another thread enumerates them in CreateEmitMethodForEnumerableServiceServiceRequest:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Linq.Enumerable+SelectManySingleSelectorIterator...
   at LightInject.ServiceContainer.CreateEmitMethodForEnumerableServiceServiceRequest(...)

With LightInject.Microsoft.DependencyInjection, CanGetInstance backs IServiceProviderIsService, which ActivatorUtilities (Hangfire, MVC, etc.) calls at runtime, so this shows up under production load.

Fix

Take lockObject in CanGetInstance. Monitor is reentrant, so nested calls from within CreateDelegate are unaffected.

Tests

Issue614 runs CanGetInstance and GetInstance concurrently for many open generic enumerables with MS compatibility enabled. It fails consistently on master (corrupted lists from concurrent List.Add) and passes with the fix. Full suite passes (1562 tests).

A separate, pre-existing issue where closed generic enumerables accumulate duplicate items in MS compatibility mode will be addressed in a follow-up PR.

🤖 Generated with Claude Code

CanGetInstance may register closed generic services while resolving the
emit method. Without taking the container lock this raced with
CreateDelegate enumerating the same registration lists, causing
"Collection was modified" exceptions under load (e.g. when used as
IServiceProviderIsService by ActivatorUtilities).

Fixes #614

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seesharper
seesharper merged commit a4f3f40 into master Sep 25, 2026
2 checks passed
@seesharper seesharper mentioned this pull request Sep 30, 2026
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.

Collection was modified exception when resolving open generics

1 participant