Commit fad6f39
Fix thread-safety races in TargetTypeDefinition member-wrapper caches
Closes #481
Root cause: PR #471 added lazy caches (ctorDefs/methDefs/fieldDefs/etc.)
in TargetTypeDefinition so wrapper objects are allocated once and shared
across all GetConstructors/GetMethods/etc. calls. When the F# compiler
invokes these from multiple threads concurrently, the lazies can be forced
concurrently, and the underlying non-thread-safe caches race:
* ILMethodDefs.getmap() / ILTypeDefs.getmap() / ILExportedTypesAndForwarders.getmap()
used a mutable null-check pattern without synchronisation. One thread
sets lmap to a new Dictionary and starts filling it; a second thread sees
the non-null lmap and reads it while the first is still writing ->
InvalidOperationException.
* mkCacheInt32 / mkCacheGeneric (binary-reader caches) had the same
unsynchronised ref-null pattern.
* TxTable<T>.Get wrote to Dictionary<int,T> without a lock; concurrent
type-resolution calls (txILTypeRef -> txTable.Get) from shared cached
MethodInfo/ConstructorInfo objects could collide.
Fixes:
* ILMethodDefs / ILTypeDefs / ILExportedTypesAndForwarders: build lmap
inside lock syncObj so the dictionary is fully populated before any
reader can see it. Subsequent calls acquire the lock, check the
already-set field and return immediately (single branch).
* mkCacheInt32 / mkCacheGeneric: each cache now holds its own lock object
and protects every TryGetValue/set_Item pair.
* TxTable<T>: backed by ConcurrentDictionary<int, Lazy<T>> so that
concurrent GetOrAdd calls for the same token race safely, with Lazy<T>
guaranteeing the factory runs exactly once per token.
Adds a thread-safety regression test: 8 threads × 50 iterations each
calling GetConstructors/GetMethods/GetFields/GetProperties/GetEvents/
GetNestedTypes on the same TargetTypeDefinition simultaneously.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 821de01 commit fad6f39
2 files changed
Lines changed: 94 additions & 53 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2874 | 2874 | | |
2875 | 2875 | | |
2876 | 2876 | | |
2877 | | - | |
| 2877 | + | |
| 2878 | + | |
2878 | 2879 | | |
2879 | | - | |
2880 | | - | |
2881 | | - | |
2882 | | - | |
2883 | | - | |
2884 | | - | |
2885 | | - | |
2886 | | - | |
| 2880 | + | |
| 2881 | + | |
| 2882 | + | |
| 2883 | + | |
| 2884 | + | |
| 2885 | + | |
| 2886 | + | |
| 2887 | + | |
| 2888 | + | |
| 2889 | + | |
2887 | 2890 | | |
2888 | 2891 | | |
2889 | 2892 | | |
| |||
3097 | 3100 | | |
3098 | 3101 | | |
3099 | 3102 | | |
3100 | | - | |
| 3103 | + | |
| 3104 | + | |
3101 | 3105 | | |
3102 | | - | |
3103 | | - | |
3104 | | - | |
3105 | | - | |
3106 | | - | |
3107 | | - | |
| 3106 | + | |
| 3107 | + | |
| 3108 | + | |
| 3109 | + | |
| 3110 | + | |
| 3111 | + | |
| 3112 | + | |
3108 | 3113 | | |
3109 | 3114 | | |
3110 | 3115 | | |
| |||
3142 | 3147 | | |
3143 | 3148 | | |
3144 | 3149 | | |
3145 | | - | |
| 3150 | + | |
| 3151 | + | |
3146 | 3152 | | |
3147 | | - | |
3148 | | - | |
3149 | | - | |
3150 | | - | |
3151 | | - | |
3152 | | - | |
| 3153 | + | |
| 3154 | + | |
| 3155 | + | |
| 3156 | + | |
| 3157 | + | |
| 3158 | + | |
| 3159 | + | |
3153 | 3160 | | |
3154 | 3161 | | |
3155 | 3162 | | |
| |||
4579 | 4586 | | |
4580 | 4587 | | |
4581 | 4588 | | |
4582 | | - | |
| 4589 | + | |
| 4590 | + | |
4583 | 4591 | | |
4584 | | - | |
4585 | | - | |
4586 | | - | |
4587 | | - | |
4588 | | - | |
4589 | | - | |
4590 | | - | |
4591 | | - | |
4592 | | - | |
4593 | | - | |
4594 | | - | |
4595 | | - | |
4596 | | - | |
| 4592 | + | |
| 4593 | + | |
| 4594 | + | |
| 4595 | + | |
| 4596 | + | |
| 4597 | + | |
| 4598 | + | |
4597 | 4599 | | |
4598 | 4600 | | |
4599 | 4601 | | |
4600 | | - | |
| 4602 | + | |
| 4603 | + | |
4601 | 4604 | | |
4602 | | - | |
4603 | | - | |
4604 | | - | |
4605 | | - | |
4606 | | - | |
4607 | | - | |
4608 | | - | |
4609 | | - | |
| 4605 | + | |
| 4606 | + | |
| 4607 | + | |
| 4608 | + | |
| 4609 | + | |
| 4610 | + | |
| 4611 | + | |
4610 | 4612 | | |
4611 | 4613 | | |
4612 | 4614 | | |
| |||
7012 | 7014 | | |
7013 | 7015 | | |
7014 | 7016 | | |
7015 | | - | |
| 7017 | + | |
7016 | 7018 | | |
7017 | | - | |
7018 | | - | |
7019 | | - | |
7020 | | - | |
7021 | | - | |
7022 | | - | |
| 7019 | + | |
| 7020 | + | |
7023 | 7021 | | |
7024 | 7022 | | |
7025 | 7023 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
511 | 511 | | |
512 | 512 | | |
513 | 513 | | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
0 commit comments