Add context cancellation to bypass.Submit

bypass.Submit now takes a context and returns early when cancelled.
This allows the stop command to properly cancel pending bypass requests
that haven't been approved or denied yet.

The full context chain is now:
1. stop command -> Interrupt -> cancel actCtx
2. actCtx cancellation -> closes CallTool fid
3. toolsrv proc/new sees closed fid -> propagates ctx cancellation
4. ExecuteTool -> executeBypassDirect -> bypass.Submit
5. bypass.Submit returns ctx.Err() when context is cancelled
This commit is contained in:
Levi Neely 2026-08-12 09:32:21 +02:00
parent 5dc7cdc2ea
commit 31681cb4e7
2 changed files with 24 additions and 6 deletions

View File

@ -4,6 +4,7 @@
package bypass
import (
"context"
"crypto/rand"
"encoding/hex"
"errors"
@ -29,10 +30,10 @@ var (
requests = make(map[string]*Request)
)
// Submit submits a bypass request and blocks until resolved.
// Submit submits a bypass request and blocks until resolved or context cancelled.
// Returns (approved, error). If denied, approved is false and error is nil.
// If there's an error (e.g., timeout, connection lost), error is non-nil.
func Submit(cmd, cwd string, env map[string]string) (bool, error) {
// If context is cancelled, returns (false, ctx.Err()).
func Submit(ctx context.Context, cmd, cwd string, env map[string]string) (bool, error) {
req := &Request{
ID: nextID(),
Cmd: cmd,
@ -45,8 +46,25 @@ func Submit(cmd, cwd string, env map[string]string) (bool, error) {
requests[req.ID] = req
mu.Unlock()
pending <- req
<-req.done
// Send to pending channel (may block if channel is full)
select {
case pending <- req:
case <-ctx.Done():
mu.Lock()
delete(requests, req.ID)
mu.Unlock()
return false, ctx.Err()
}
// Wait for resolution or context cancellation
select {
case <-req.done:
case <-ctx.Done():
mu.Lock()
delete(requests, req.ID)
mu.Unlock()
return false, ctx.Err()
}
mu.Lock()
delete(requests, req.ID)

View File

@ -240,7 +240,7 @@ func executeBypassDirect(ctx context.Context, cmd, cwd string, envExtra map[stri
}
// Submit bypass request and wait for approval
approved, err := bypass.Submit(cmd, cwd, envMap)
approved, err := bypass.Submit(ctx, cmd, cwd, envMap)
if err != nil {
return "", fmt.Errorf("bypass request failed: %w", err)
}