Files
rvbox/internal/client/supervisor/windows/native_other.go
T

81 lines
2.6 KiB
Go

//go:build !windows
package windows
import (
"context"
"errors"
"os"
"time"
"github.com/rvbox/rvbox/internal/client/supervisor"
)
func stdinLineEnding() []byte { return []byte{'\n'} }
// NewSupervisor returns the deterministic local adapter used by tests and by
// non-Windows development builds. The v1 client does not advertise this
// adapter as a supported Unix client; it exists so protocol/runtime tests can
// exercise real child processes without a Windows host.
func NewSupervisor(options NativeOptions) (supervisor.Supervisor, error) {
return newExecSupervisor(options), nil
}
func (manager *execSupervisor) Start(ctx context.Context, spec supervisor.StartSpec) (supervisor.Process, error) {
return manager.startPortable(ctx, spec)
}
func (manager *execSupervisor) Signal(ctx context.Context, process supervisor.Process, signal supervisor.SignalKind) (supervisor.SignalOutcome, error) {
if process == nil {
return supervisor.SignalOutcome{}, ErrProcessNotFound
}
executable, ok := process.(*execProcess)
if !ok {
return supervisor.SignalOutcome{}, ErrProcessNotFound
}
if signal != supervisor.SignalTerm && signal != supervisor.SignalKill {
return supervisor.SignalOutcome{}, errors.New("unsupported signal")
}
if signal == supervisor.SignalTerm {
if executable.cmd.Process != nil {
_ = executable.cmd.Process.Signal(os.Interrupt)
}
select {
case <-ctx.Done():
return supervisor.SignalOutcome{}, ctx.Err()
case <-time.After(manager.options.WindowsTermGrace):
}
}
if err := executable.terminate(1); err != nil {
return supervisor.SignalOutcome{}, err
}
return supervisor.SignalOutcome{Delivered: true, Escalated: signal == supervisor.SignalTerm, Detail: "process terminated", ObservedAt: manager.options.Now()}, nil
}
func (manager *execSupervisor) Snapshot(ctx context.Context, process supervisor.Process) (supervisor.ResourceSnapshot, error) {
if process == nil {
return supervisor.ResourceSnapshot{}, ErrProcessNotFound
}
select {
case <-ctx.Done():
return supervisor.ResourceSnapshot{}, ctx.Err()
default:
}
return supervisor.ResourceSnapshot{ProcessCount: 1, ObservedAt: manager.options.Now(), Complete: false, Detail: "portable adapter does not expose aggregate process accounting"}, nil
}
func (manager *execSupervisor) StopAll(_ context.Context) error {
manager.mu.Lock()
processes := make([]*execProcess, 0, len(manager.active))
for _, process := range manager.active {
processes = append(processes, process)
}
manager.mu.Unlock()
for _, process := range processes {
if err := process.terminate(1); err != nil && !errors.Is(err, os.ErrProcessDone) {
return err
}
}
return nil
}