/internal/storage/dolt: fix windows build issue
This commit is contained in:
15
internal/storage/dolt/procattr_unix.go
Normal file
15
internal/storage/dolt/procattr_unix.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package dolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setDoltServerSysProcAttr(cmd *exec.Cmd) {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
12
internal/storage/dolt/procattr_windows.go
Normal file
12
internal/storage/dolt/procattr_windows.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package dolt
|
||||||
|
|
||||||
|
import "os/exec"
|
||||||
|
|
||||||
|
// Windows does not support Setpgid; leave default process attributes.
|
||||||
|
func setDoltServerSysProcAttr(cmd *exec.Cmd) {
|
||||||
|
// no-op
|
||||||
|
_ = cmd
|
||||||
|
}
|
||||||
32
internal/storage/dolt/process_unix.go
Normal file
32
internal/storage/dolt/process_unix.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package dolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processMayBeAlive(p *os.Process) bool {
|
||||||
|
// Signal 0 checks for existence without sending a real signal.
|
||||||
|
if err := p.Signal(syscall.Signal(0)); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func terminateProcess(p *os.Process) error {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := p.Signal(syscall.SIGTERM); err != nil {
|
||||||
|
// Process may already be dead; treat as success.
|
||||||
|
if strings.Contains(err.Error(), "process already finished") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
21
internal/storage/dolt/process_windows.go
Normal file
21
internal/storage/dolt/process_windows.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package dolt
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func processMayBeAlive(p *os.Process) bool {
|
||||||
|
// Windows doesn't support Unix-style signal(0) checks. Treat as "unknown/alive"
|
||||||
|
// and let connection attempts / wait timeouts determine readiness.
|
||||||
|
_ = p
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func terminateProcess(p *os.Process) error {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Best-effort: Windows doesn't have SIGTERM semantics; kill the process.
|
||||||
|
return p.Kill()
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -107,10 +106,8 @@ func (s *Server) Start(ctx context.Context) error {
|
|||||||
s.cmd = exec.CommandContext(ctx, "dolt", args...)
|
s.cmd = exec.CommandContext(ctx, "dolt", args...)
|
||||||
s.cmd.Dir = s.cfg.DataDir
|
s.cmd.Dir = s.cfg.DataDir
|
||||||
|
|
||||||
// Set up process group for clean shutdown
|
// Set up process group for clean shutdown (Unix-only; no-op on Windows).
|
||||||
s.cmd.SysProcAttr = &syscall.SysProcAttr{
|
setDoltServerSysProcAttr(s.cmd)
|
||||||
Setpgid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up logging
|
// Set up logging
|
||||||
if s.cfg.LogFile != "" {
|
if s.cfg.LogFile != "" {
|
||||||
@@ -163,13 +160,8 @@ func (s *Server) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try graceful shutdown first (SIGTERM)
|
// Best-effort graceful shutdown (platform-specific).
|
||||||
if err := s.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
_ = terminateProcess(s.cmd.Process)
|
||||||
// Process may already be dead
|
|
||||||
if !strings.Contains(err.Error(), "process already finished") {
|
|
||||||
return fmt.Errorf("failed to send SIGTERM: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for graceful shutdown with timeout
|
// Wait for graceful shutdown with timeout
|
||||||
done := make(chan error, 1)
|
done := make(chan error, 1)
|
||||||
@@ -250,11 +242,9 @@ func (s *Server) waitForReady(ctx context.Context) error {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if process is still alive using signal 0
|
// Best-effort: if we can tell the process is dead, fail fast.
|
||||||
if s.cmd.Process != nil {
|
if s.cmd.Process != nil && !processMayBeAlive(s.cmd.Process) {
|
||||||
if err := s.cmd.Process.Signal(syscall.Signal(0)); err != nil {
|
return fmt.Errorf("server process exited unexpectedly")
|
||||||
return fmt.Errorf("server process exited unexpectedly")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to connect
|
// Try to connect
|
||||||
@@ -290,9 +280,8 @@ func GetRunningServerPID(dataDir string) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Unix, FindProcess always succeeds, so we need to check if it's alive
|
// Best-effort liveness check (platform-specific).
|
||||||
if err := process.Signal(syscall.Signal(0)); err != nil {
|
if !processMayBeAlive(process) {
|
||||||
// Process is not running
|
|
||||||
_ = os.Remove(pidFile)
|
_ = os.Remove(pidFile)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -307,13 +296,8 @@ func StopServerByPID(pid int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try graceful shutdown first
|
// Best-effort graceful shutdown (platform-specific).
|
||||||
if err := process.Signal(syscall.SIGTERM); err != nil {
|
_ = terminateProcess(process)
|
||||||
if !strings.Contains(err.Error(), "process already finished") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for graceful shutdown
|
// Wait for graceful shutdown
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|||||||
Reference in New Issue
Block a user