Reserve toolsrv process slots atomically
This commit is contained in:
parent
562e1ef780
commit
b6009f0f7a
|
|
@ -38,10 +38,11 @@ type State struct {
|
|||
pathLocks pathLockTable
|
||||
|
||||
// Process management
|
||||
procMu sync.Mutex
|
||||
procs map[int]*Proc
|
||||
nextID int
|
||||
procLimit int
|
||||
procMu sync.Mutex
|
||||
procs map[int]*Proc
|
||||
nextID int
|
||||
procLimit int
|
||||
procReserved int
|
||||
|
||||
// Callbacks
|
||||
OnToolsChanged func()
|
||||
|
|
@ -223,13 +224,23 @@ func (st *State) NewProc(ctx context.Context, payload string, background bool) (
|
|||
return "", 0, fmt.Errorf("missing 'tool' in payload")
|
||||
}
|
||||
|
||||
// Check proc limit
|
||||
// Reserve a process slot before setup so concurrent callers cannot all pass
|
||||
// the limit check while their processes are still being initialized.
|
||||
st.procMu.Lock()
|
||||
if len(st.procs) >= st.procLimit {
|
||||
if len(st.procs)+st.procReserved >= st.procLimit {
|
||||
st.procMu.Unlock()
|
||||
return "", 0, fmt.Errorf("process limit reached (%d)", st.procLimit)
|
||||
}
|
||||
st.procReserved++
|
||||
st.procMu.Unlock()
|
||||
reserved := true
|
||||
defer func() {
|
||||
if reserved {
|
||||
st.procMu.Lock()
|
||||
st.procReserved--
|
||||
st.procMu.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
// Look up tool
|
||||
st.mu.RLock()
|
||||
|
|
@ -289,7 +300,9 @@ func (st *State) NewProc(ctx context.Context, payload string, background bool) (
|
|||
|
||||
st.procMu.Lock()
|
||||
st.procs[proc.ID] = proc
|
||||
st.procReserved--
|
||||
st.procMu.Unlock()
|
||||
reserved = false
|
||||
|
||||
// For background procs, stream output directly into the proc buffer.
|
||||
// For foreground, use nil (local buffer in exec path).
|
||||
|
|
|
|||
Loading…
Reference in New Issue