Skip to content

Commit a7db811

Browse files
authored
Always check refCount after acquiring lock (#1986)
1 parent a27091b commit a7db811

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

internal/project/extendedconfigcache.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ func (c *ExtendedConfigCache) Acquire(fh FileHandle, path tspath.Path, parse fun
3838
func (c *ExtendedConfigCache) Ref(path tspath.Path) {
3939
if entry, ok := c.entries.Load(path); ok {
4040
entry.mu.Lock()
41+
if entry.refCount <= 0 {
42+
// Entry was deleted while we were acquiring the lock
43+
newEntry, loaded := c.loadOrStoreNewLockedEntry(path)
44+
if !loaded {
45+
newEntry.entry = entry.entry
46+
newEntry.hash = entry.hash
47+
}
48+
entry.mu.Unlock()
49+
newEntry.mu.Unlock()
50+
return
51+
}
4152
entry.refCount++
4253
entry.mu.Unlock()
4354
}
@@ -48,10 +59,10 @@ func (c *ExtendedConfigCache) Deref(path tspath.Path) {
4859
entry.mu.Lock()
4960
entry.refCount--
5061
remove := entry.refCount <= 0
51-
entry.mu.Unlock()
5262
if remove {
5363
c.entries.Delete(path)
5464
}
65+
entry.mu.Unlock()
5566
}
5667
}
5768

@@ -68,6 +79,11 @@ func (c *ExtendedConfigCache) loadOrStoreNewLockedEntry(path tspath.Path) (*exte
6879
entry.mu.Lock()
6980
if existing, loaded := c.entries.LoadOrStore(path, entry); loaded {
7081
existing.mu.Lock()
82+
if existing.refCount <= 0 {
83+
// Entry was deleted while we were acquiring the lock
84+
existing.mu.Unlock()
85+
return c.loadOrStoreNewLockedEntry(path)
86+
}
7187
existing.refCount++
7288
return existing, true
7389
}

internal/project/parsecache.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ func (c *ParseCache) Ref(file *ast.SourceFile) {
6363
key := newParseCacheKey(file.ParseOptions(), file.ScriptKind)
6464
if entry, ok := c.entries.Load(key); ok {
6565
entry.mu.Lock()
66+
if entry.refCount <= 0 && !c.Options.DisableDeletion {
67+
// Entry was deleted while we were acquiring the lock
68+
newEntry, loaded := c.loadOrStoreNewLockedEntry(key)
69+
if !loaded {
70+
newEntry.sourceFile = entry.sourceFile
71+
newEntry.hash = entry.hash
72+
}
73+
entry.mu.Unlock()
74+
newEntry.mu.Unlock()
75+
return
76+
}
6677
entry.refCount++
6778
entry.mu.Unlock()
6879
} else {
@@ -76,10 +87,10 @@ func (c *ParseCache) Deref(file *ast.SourceFile) {
7687
entry.mu.Lock()
7788
entry.refCount--
7889
remove := entry.refCount <= 0
79-
entry.mu.Unlock()
8090
if !c.Options.DisableDeletion && remove {
8191
c.entries.Delete(key)
8292
}
93+
entry.mu.Unlock()
8394
}
8495
}
8596

@@ -92,6 +103,11 @@ func (c *ParseCache) loadOrStoreNewLockedEntry(key parseCacheKey) (*parseCacheEn
92103
existing, loaded := c.entries.LoadOrStore(key, entry)
93104
if loaded {
94105
existing.mu.Lock()
106+
if existing.refCount <= 0 && !c.Options.DisableDeletion {
107+
// Existing entry was deleted while we were acquiring the lock
108+
existing.mu.Unlock()
109+
return c.loadOrStoreNewLockedEntry(key)
110+
}
95111
existing.refCount++
96112
return existing, true
97113
}

0 commit comments

Comments
 (0)