Skip to content

Commit 8c3243d

Browse files
committed
Correct locking for condition variable
1 parent d1ee1ba commit 8c3243d

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

Diff for: handler/handler.go

+32-23
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,21 @@ func (handler *InoHandler) dataRUnlock(msg string) {
9797
handler.dataMux.RUnlock()
9898
}
9999

100-
func (handler *InoHandler) waitClangdStart(msg string) {
101-
log.Println(msg + yellow.Sprintf(" unlocked (waiting clangd)"))
100+
func (handler *InoHandler) waitClangdStart(prefix string) error {
101+
if handler.ClangdConn != nil {
102+
return nil
103+
}
104+
105+
log.Printf(prefix + "(throttled: waiting for clangd)")
106+
log.Println(prefix + yellow.Sprintf(" unlocked (waiting clangd)"))
102107
handler.clangdStarted.Wait()
103-
log.Println(msg + yellow.Sprintf(" locked (waiting clangd)"))
108+
log.Println(prefix + yellow.Sprintf(" locked (waiting clangd)"))
109+
110+
if handler.ClangdConn == nil {
111+
log.Printf(prefix + "clangd startup failed: aborting call")
112+
return errors.New("could not start clangd, aborted")
113+
}
114+
return nil
104115
}
105116

106117
// NewInoHandler creates and configures an InoHandler.
@@ -165,37 +176,35 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
165176
params = req.Params
166177
}
167178

179+
// Set up RWLocks and wait for clangd startup
168180
switch req.Method {
169-
case // Write lock
170-
"initialize",
181+
case // Write lock - NO clangd required
182+
"initialize":
183+
handler.dataLock(prefix)
184+
defer handler.dataUnlock(prefix)
185+
case // Write lock - clangd required
171186
"textDocument/didOpen",
172187
"textDocument/didChange",
173188
"textDocument/didClose":
174189
handler.dataLock(prefix)
175190
defer handler.dataUnlock(prefix)
176-
case // Read lock
177-
"textDocument/publishDiagnostics",
178-
"workspace/applyEdit":
191+
handler.waitClangdStart(prefix)
192+
case // Read lock - NO clangd required
193+
"initialized":
179194
handler.dataRLock(prefix)
180195
defer handler.dataRUnlock(prefix)
181-
default: // Default to read lock
196+
default: // Read lock - clangd required
182197
handler.dataRLock(prefix)
183-
defer handler.dataRUnlock(prefix)
184-
}
185-
186-
switch req.Method {
187-
case // Do not need clangd
188-
"initialize",
189-
"initialized":
190-
default: // Default to clangd required
191-
// Wait for clangd start-up
198+
// if clangd is not started...
192199
if handler.ClangdConn == nil {
193-
log.Printf(prefix + "(throttled: waiting for clangd)")
200+
// Release the read lock and acquire a write lock
201+
// (this is required to wait on condition variable).
202+
handler.dataRUnlock(prefix)
203+
handler.dataLock(prefix)
204+
defer handler.dataUnlock(prefix)
194205
handler.waitClangdStart(prefix)
195-
if handler.ClangdConn == nil {
196-
log.Printf(prefix + "clangd startup failed: aborting call")
197-
return nil, errors.New("could not start clangd, aborted")
198-
}
206+
} else {
207+
defer handler.dataRUnlock(prefix)
199208
}
200209
}
201210

0 commit comments

Comments
 (0)