Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c95d401a36 | ||
|
|
f7ea30a494 | ||
|
|
620be9d57c |
@@ -68,9 +68,9 @@ func parseFlags(args []string) (configPath string, install, remove, noCopy, help
|
||||
i++
|
||||
case strings.HasPrefix(args[i], "-config="):
|
||||
configPath = strings.TrimPrefix(args[i], "-config=")
|
||||
case args[i] == "--install-service" || args[i] == "-install-service":
|
||||
case args[i] == "--install-service" || args[i] == "-install-service" || args[i] == "-i":
|
||||
install = true
|
||||
case args[i] == "--remove-service" || args[i] == "-remove-service":
|
||||
case args[i] == "--remove-service" || args[i] == "-remove-service" || args[i] == "-r":
|
||||
remove = true
|
||||
case args[i] == "--no-copy" || args[i] == "-no-copy":
|
||||
noCopy = true
|
||||
@@ -82,7 +82,7 @@ func parseFlags(args []string) (configPath string, install, remove, noCopy, help
|
||||
forceUpdate = true
|
||||
case args[i] == "--update-now" || args[i] == "-update-now":
|
||||
updateNow = true
|
||||
case args[i] == "--monitor" || args[i] == "-monitor":
|
||||
case args[i] == "--monitor" || args[i] == "-monitor" || args[i] == "-m":
|
||||
monitor = true
|
||||
case args[i] == "--elevated-child":
|
||||
elevatedChild = true
|
||||
@@ -100,15 +100,16 @@ const usageText = `GPU arbitration proxy for Ollama + ComfyUI
|
||||
|
||||
Usage:
|
||||
gpu-turnstile -config <path> run the proxy
|
||||
gpu-turnstile --install-service [--no-copy] [-config path] install + start as a service
|
||||
gpu-turnstile --remove-service stop + uninstall the service
|
||||
gpu-turnstile -i | --install-service [--no-copy] [-config path]
|
||||
install + start as a service
|
||||
gpu-turnstile -r | --remove-service stop + uninstall the service
|
||||
gpu-turnstile -v | --version print just the version
|
||||
gpu-turnstile --force-update check for a signed update now,
|
||||
apply it and restart the service
|
||||
(no admin needed when the service runs)
|
||||
gpu-turnstile --update-now like --force-update, but only
|
||||
through the running service
|
||||
gpu-turnstile --monitor live status view (downstreams,
|
||||
gpu-turnstile -m | --monitor live status view (downstreams,
|
||||
GPU lock, queue); Ctrl+C quits
|
||||
gpu-turnstile -h | --help this help
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# ComfyUI --listen 0.0.0.0 --port 8189).
|
||||
services:
|
||||
gpu-turnstile:
|
||||
image: git.rambossek.at/public/gpu-turnstile:v0.2.4
|
||||
image: git.rambossek.at/public/gpu-turnstile:v0.2.5
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# Each consumer is enabled by setting its URL; leave one unset to
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@@ -78,19 +79,43 @@ func Serve(ctx context.Context, h Handler, log *slog.Logger) error {
|
||||
}
|
||||
go func() {
|
||||
// Blocks until a client connects; on process exit the
|
||||
// handle goes away with everything else.
|
||||
if err := windows.ConnectNamedPipe(pipe, nil); err != nil {
|
||||
// handle goes away with everything else. A client that
|
||||
// raced us and connected between CreateNamedPipe and
|
||||
// ConnectNamedPipe reports ERROR_PIPE_CONNECTED — that is
|
||||
// a success, not a failure.
|
||||
if err := windows.ConnectNamedPipe(pipe, nil); err != nil && err != errnoPipeConnected {
|
||||
windows.CloseHandle(pipe)
|
||||
return
|
||||
}
|
||||
f := os.NewFile(uintptr(pipe), pipePath)
|
||||
serveConn(f, h) // closes f, and with it the pipe handle
|
||||
serveConn(&pipeConn{f: os.NewFile(uintptr(pipe), pipePath), h: pipe}, h)
|
||||
}()
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// errnoPipeConnected is ConnectNamedPipe's "the client connected before we
|
||||
// called" result, which means the connection is established.
|
||||
var errnoPipeConnected = syscall.Errno(535) // ERROR_PIPE_CONNECTED
|
||||
|
||||
// pipeConn adapts a pipe handle to io.ReadWriteCloser. Close flushes first
|
||||
// (FlushFileBuffers blocks until the client has read the reply) and then
|
||||
// disconnects — closing the bare handle right after writing can discard
|
||||
// unread reply bytes, which clients see as an empty, failed request.
|
||||
type pipeConn struct {
|
||||
f *os.File
|
||||
h windows.Handle
|
||||
}
|
||||
|
||||
func (c *pipeConn) Read(p []byte) (int, error) { return c.f.Read(p) }
|
||||
func (c *pipeConn) Write(p []byte) (int, error) { return c.f.Write(p) }
|
||||
|
||||
func (c *pipeConn) Close() error {
|
||||
windows.FlushFileBuffers(c.h) //nolint:errcheck // best effort
|
||||
windows.DisconnectNamedPipe(c.h) //nolint:errcheck // best effort
|
||||
return c.f.Close()
|
||||
}
|
||||
|
||||
// Ask sends one command to the running service and returns its reply.
|
||||
func Ask(cmd string) (string, error) {
|
||||
name, err := windows.UTF16PtrFromString(pipePath)
|
||||
|
||||
Reference in New Issue
Block a user