execute: timeout=0 means no timeout
Allows long-running daemons to be started without a deadline. timeout < 0 still defaults to 30s. Schema descriptions updated.
This commit is contained in:
parent
5df603a9e3
commit
c0a52a8031
|
|
@ -517,6 +517,25 @@ func TestRunReadBatch_WithLockDir(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTimeoutZeroNoDeadline(t *testing.T) {
|
||||
s := newServer(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// timeout=0 should not kill the process after 30s default.
|
||||
// We verify by running a 2s sleep with timeout=0 and detaching it.
|
||||
// If timeout were applied, it would use default 30s which is fine,
|
||||
// but we confirm it doesn't fail with timeout=0.
|
||||
done := make(chan string, 1)
|
||||
go func() {
|
||||
out, _ := s.Execute(ctx, "echo alive; sleep 1; echo done", "bash", 0, "default", true)
|
||||
done <- out
|
||||
}()
|
||||
out := <-done
|
||||
if !strings.Contains(out, "done") {
|
||||
t.Errorf("expected 'done' in output, got: %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- detach ----
|
||||
|
||||
func TestDetach(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ Examples:
|
|||
}
|
||||
}
|
||||
},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per step (default: 30)."},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per step (default: 30). Use 0 for no timeout."},
|
||||
"sandbox": {"type": "string", "description": "Sandbox name (default: default)."}
|
||||
}
|
||||
}`),
|
||||
|
|
@ -244,7 +244,7 @@ Examples:
|
|||
}
|
||||
}
|
||||
},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per call (default: 30)."},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per call (default: 30). Use 0 for no timeout."},
|
||||
"sandbox": {"type": "string", "description": "Sandbox name (default: default)."}
|
||||
}
|
||||
}`),
|
||||
|
|
@ -301,7 +301,7 @@ Examples:
|
|||
}
|
||||
}
|
||||
},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per stage (default: 30)."},
|
||||
"timeout": {"type": "integer", "description": "Timeout in seconds per stage (default: 30). Use 0 for no timeout."},
|
||||
"sandbox": {"type": "string", "description": "Sandbox name (default: default)."}
|
||||
}
|
||||
}`),
|
||||
|
|
@ -484,7 +484,7 @@ func (e *Server) Execute(ctx context.Context, code, language string, timeout int
|
|||
// executeWithStdin is like Execute but feeds stdinData to the command's stdin.
|
||||
// For languages where code is itself passed via stdin (ed, expect, bc), stdinData is ignored.
|
||||
func (e *Server) executeWithStdin(ctx context.Context, code, language string, timeout int, sandboxName string, trusted bool, stdinData string) (string, error) {
|
||||
if timeout <= 0 {
|
||||
if timeout < 0 {
|
||||
timeout = 30
|
||||
}
|
||||
|
||||
|
|
@ -512,7 +512,13 @@ func (e *Server) executeWithStdin(ctx context.Context, code, language string, ti
|
|||
workDir, _ = os.Getwd()
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
|
||||
var cancel context.CancelFunc
|
||||
if timeout > 0 {
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
|
||||
} else {
|
||||
// timeout=0 means no timeout (run indefinitely, e.g. for daemons)
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
}
|
||||
// NOTE: do NOT defer cancel() here — the detach path must avoid cancelling
|
||||
// the context (which would kill the detached process via cmd.Cancel).
|
||||
// Each exit path calls cancel() explicitly except detach.
|
||||
|
|
|
|||
Reference in New Issue