Skip to content

Commit f105888

Browse files
Martin521psfinakivzarytovskii
authored
fix for race condition in FileIndex.fileIndexOfFile (#18008)
* fix for race condition in FileIndex.fileIndexOfFile * fantomas * fixed ilverify baselines (just a single line number changed) * add release notes entry * FileToIndex: Added unlocked read so that lock is entered for new files only * update ilverify baselines (changed line numbers only) * Fix ILVerify --------- Co-authored-by: Petr <[email protected]> Co-authored-by: Vlad Zarytovskii <[email protected]>
1 parent 64bb76c commit f105888

File tree

8 files changed

+64
-36
lines changed

8 files changed

+64
-36
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.200.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* Fix locals allocating for the special `copyOfStruct` defensive copy ([PR #18025](https://github.com/dotnet/fsharp/pull/18025))
1616
* Fix lowering of computed array expressions when the expression consists of a simple mapping from a `uint64` or `unativeint` array. [PR #18081](https://github.com/dotnet/fsharp/pull/18081)
1717
* Add missing nullable-metadata for C# consumers of records,exceptions and DU subtypes generated from F# code. [PR #18079](https://github.com/dotnet/fsharp/pull/18079)
18+
* Fix a race condition in file book keeping in the compiler service ([#18008](https://github.com/dotnet/fsharp/pull/18008))
1819

1920

2021
### Added

src/Compiler/Utilities/range.fs

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -196,38 +196,43 @@ type FileIndexTable() =
196196
match fileToIndexTable.TryGetValue filePath with
197197
| true, idx -> idx
198198
| _ ->
199-
200-
// Try again looking for a normalized entry.
201-
let normalizedFilePath =
202-
if normalize then
203-
FileSystem.NormalizePathShim filePath
204-
else
205-
filePath
206-
207-
match fileToIndexTable.TryGetValue normalizedFilePath with
208-
| true, idx ->
209-
// Record the non-normalized entry if necessary
210-
if filePath <> normalizedFilePath then
211-
lock fileToIndexTable (fun () -> fileToIndexTable[filePath] <- idx)
212-
213-
// Return the index
214-
idx
215-
216-
| _ ->
217-
lock fileToIndexTable (fun () ->
218-
// Get the new index
219-
let idx = indexToFileTable.Count
220-
221-
// Record the normalized entry
222-
indexToFileTable.Add normalizedFilePath
223-
fileToIndexTable[normalizedFilePath] <- idx
224-
225-
// Record the non-normalized entry if necessary
226-
if filePath <> normalizedFilePath then
227-
fileToIndexTable[filePath] <- idx
228-
229-
// Return the index
230-
idx)
199+
// If a write operation can happen, we have to lock the whole read-check-write to avoid race conditions
200+
lock fileToIndexTable
201+
<| fun () ->
202+
match fileToIndexTable.TryGetValue filePath with
203+
| true, idx -> idx
204+
| _ ->
205+
206+
// Try again looking for a normalized entry.
207+
let normalizedFilePath =
208+
if normalize then
209+
FileSystem.NormalizePathShim filePath
210+
else
211+
filePath
212+
213+
match fileToIndexTable.TryGetValue normalizedFilePath with
214+
| true, idx ->
215+
// Record the non-normalized entry if necessary
216+
if filePath <> normalizedFilePath then
217+
fileToIndexTable[filePath] <- idx
218+
219+
// Return the index
220+
idx
221+
222+
| _ ->
223+
// Get the new index
224+
let idx = indexToFileTable.Count
225+
226+
// Record the normalized entry
227+
indexToFileTable.Add normalizedFilePath
228+
fileToIndexTable[normalizedFilePath] <- idx
229+
230+
// Record the non-normalized entry if necessary
231+
if filePath <> normalizedFilePath then
232+
fileToIndexTable[filePath] <- idx
233+
234+
// Return the index
235+
idx
231236

232237
member t.IndexToFile n =
233238
if n < 0 then

tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
<Compile Include="Miscellaneous\MigratedOverloadTests.fs" />
318318
<Compile Include="Miscellaneous\MigratedTypeCheckTests.fs" />
319319
<Compile Include="Miscellaneous\GraphTests.fs" />
320+
<Compile Include="Miscellaneous\FileIndex.fs" />
320321
<Compile Include="Signatures\TestHelpers.fs" />
321322
<Compile Include="Signatures\ModuleOrNamespaceTests.fs" />
322323
<Compile Include="Signatures\RecordTests.fs" />
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module Miscellaneous.FileIndex
2+
3+
open FSharp.Compiler.Text
4+
open System.Threading.Tasks
5+
open Xunit
6+
7+
// This is a regression test for a bug that existed in FileIndex.fileIndexOfFile
8+
[<Fact>]
9+
let NoRaceCondition() =
10+
let parallelOptions = ParallelOptions()
11+
let mutable count = 10000
12+
while count > 0 do
13+
let file = $"test{count}.fs"
14+
let files = Array.create 2 file
15+
let indices = Array.create 2 -1
16+
let getFileIndex i = indices[i] <- FileIndex.fileIndexOfFile files[i]
17+
Parallel.For(0, files.Length, parallelOptions, getFileIndex) |> ignore
18+
if indices[0] <> indices[1] then
19+
Assert.Fail $"Found different indices: {indices[0]} and {indices[1]}"
20+
count <- count - 1
21+

tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_net9.0.bsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
[IL]: Error [StackUnexpected]: : FSharp.Compiler.AbstractIL.IL::parseILVersion(string)][offset 0x0000000B][found Char] Unexpected type on the stack.
6060
[IL]: Error [StackUnexpected]: : FSharp.Compiler.AbstractIL.IL::parseILVersion(string)][offset 0x00000021][found Char] Unexpected type on the stack.
6161
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharp.Compiler.DiagnosticsLogger::.cctor()][offset 0x000000CD][found Char] Unexpected type on the stack.
62-
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@543::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
62+
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@548::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
6363
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000037][found Char] Unexpected type on the stack.
6464
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000043][found Char] Unexpected type on the stack.
6565
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$Internal.Utilities.XmlAdapters::.cctor()][offset 0x0000000A][found Char] Unexpected type on the stack.

tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netstandard2.0.bsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
[IL]: Error [StackUnexpected]: : Internal.Utilities.FSharpEnvironment+probePathForDotnetHost@321::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000028][found Char] Unexpected type on the stack.
8585
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver+Pipe #6 input at line 68@68::FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver.Resolve([FSharp.Compiler.Service]FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, [S.P.CoreLib]System.Tuple`2<string,string>[], string, [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<string>, string, string, [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<string>, string, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.Unit>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<bool,Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.Unit>>>)][offset 0x0000034D][found Char] Unexpected type on the stack.
8686
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharp.Compiler.DiagnosticsLogger::.cctor()][offset 0x000000CD][found Char] Unexpected type on the stack.
87-
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@543::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
87+
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@548::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
8888
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000037][found Char] Unexpected type on the stack.
8989
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000043][found Char] Unexpected type on the stack.
9090
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$Internal.Utilities.XmlAdapters::.cctor()][offset 0x0000000A][found Char] Unexpected type on the stack.

tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net9.0.bsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
[IL]: Error [StackUnexpected]: : FSharp.Compiler.AbstractIL.IL::parseILVersion(string)][offset 0x0000000B][found Char] Unexpected type on the stack.
8686
[IL]: Error [StackUnexpected]: : FSharp.Compiler.AbstractIL.IL::parseILVersion(string)][offset 0x00000021][found Char] Unexpected type on the stack.
8787
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharp.Compiler.DiagnosticsLogger::.cctor()][offset 0x000000B6][found Char] Unexpected type on the stack.
88-
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@543::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
88+
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@548::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
8989
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000035][found Char] Unexpected type on the stack.
9090
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000041][found Char] Unexpected type on the stack.
9191
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$Internal.Utilities.XmlAdapters::.cctor()][offset 0x0000000A][found Char] Unexpected type on the stack.

tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
[IL]: Error [StackUnexpected]: : Internal.Utilities.FSharpEnvironment::probePathForDotnetHost@320([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x0000002A][found Char] Unexpected type on the stack.
112112
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver+SimulatedMSBuildResolver@68::FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver.Resolve([FSharp.Compiler.Service]FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, [S.P.CoreLib]System.Tuple`2<string,string>[], string, [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<string>, string, string, [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<string>, string, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.Unit>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<bool,Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.FSharpFunc`2<string,Microsoft.FSharp.Core.Unit>>>)][offset 0x000002F5][found Char] Unexpected type on the stack.
113113
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharp.Compiler.DiagnosticsLogger::.cctor()][offset 0x000000B6][found Char] Unexpected type on the stack.
114-
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@543::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
114+
[IL]: Error [CallVirtOnValueType]: : FSharp.Compiler.Text.RangeModule+comparer@548::System.Collections.Generic.IEqualityComparer<FSharp.Compiler.Text.Range>.GetHashCode([FSharp.Compiler.Service]FSharp.Compiler.Text.Range)][offset 0x00000002] Callvirt on a value type method.
115115
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000035][found Char] Unexpected type on the stack.
116116
[IL]: Error [StackUnexpected]: : Internal.Utilities.PathMapModule::applyDir([FSharp.Compiler.Service]Internal.Utilities.PathMap, string)][offset 0x00000041][found Char] Unexpected type on the stack.
117117
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$Internal.Utilities.XmlAdapters::.cctor()][offset 0x0000000A][found Char] Unexpected type on the stack.

0 commit comments

Comments
 (0)