55 lines
1.1 KiB
Go
55 lines
1.1 KiB
Go
//go:build linux
|
|
|
|
package control
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"net"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// sockPath lives in the unit's RuntimeDirectory; mode 0666 lets every
|
|
// local user ask, nothing can reach it from off the machine.
|
|
const sockPath = "/run/gpu-turnstile/control.sock"
|
|
|
|
// Serve starts the socket listener in the background and returns; only a
|
|
// setup failure is reported. Each client connection is answered in its own
|
|
// goroutine.
|
|
func Serve(ctx context.Context, h Handler, log *slog.Logger) error {
|
|
os.Remove(sockPath) // stale socket from a previous run
|
|
ln, err := net.Listen("unix", sockPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.Chmod(sockPath, 0o666); err != nil {
|
|
ln.Close()
|
|
return err
|
|
}
|
|
go func() {
|
|
<-ctx.Done()
|
|
ln.Close()
|
|
}()
|
|
go func() {
|
|
for {
|
|
c, err := ln.Accept()
|
|
if err != nil {
|
|
return // shutting down
|
|
}
|
|
go serveConn(c, h)
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// Ask sends one command to the running service and returns its reply.
|
|
func Ask(cmd string) (string, error) {
|
|
c, err := net.DialTimeout("unix", sockPath, 2*time.Second)
|
|
if err != nil {
|
|
return "", ErrUnavailable
|
|
}
|
|
defer c.Close()
|
|
return readReply(c, cmd)
|
|
}
|