fix: write correct child process PID to PID file
The Write() method was using os.Getpid() which writes the parent's PID instead of the spawned child process PID. Added WritePID() method to explicitly write a specific PID and added process verification after spawn.
This commit is contained in:
parent
f62439c8d6
commit
998c49e52d
2 changed files with 24 additions and 8 deletions
|
|
@ -44,24 +44,30 @@ func NewPIDFile(path string) *PIDFile {
|
|||
// This prevents multiple instances of the gateway from running simultaneously,
|
||||
// which could cause resource conflicts and undefined behavior.
|
||||
func (p *PIDFile) Write() error {
|
||||
return p.WritePID(os.Getpid())
|
||||
}
|
||||
|
||||
// WritePID atomically writes the specified process ID to the PID file.
|
||||
// Returns an error if a PID file already exists with a running process.
|
||||
//
|
||||
// Use this method when you need to write a PID other than the current process,
|
||||
// such as when spawning a child process.
|
||||
func (p *PIDFile) WritePID(pid int) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// Check for existing PID file
|
||||
if _, err := os.Stat(p.path); err == nil {
|
||||
// PID file exists, check if process is running
|
||||
pid, err := p.read()
|
||||
if err == nil && p.isProcessRunning(pid) {
|
||||
existingPid, err := p.read()
|
||||
if err == nil && p.isProcessRunning(existingPid) {
|
||||
return &ProcessRunningError{
|
||||
pid: pid,
|
||||
pid: existingPid,
|
||||
Path: p.path,
|
||||
}
|
||||
}
|
||||
// Process is not running, stale PID file, continue
|
||||
}
|
||||
|
||||
// Write PID to temp file in same directory (atomic preparation)
|
||||
pid := os.Getpid()
|
||||
pidStr := strconv.Itoa(pid)
|
||||
|
||||
tempFile := p.path + ".tmp"
|
||||
|
|
|
|||
|
|
@ -150,14 +150,24 @@ func (s *Service) Start() error {
|
|||
|
||||
pid := cmd.Process.Pid
|
||||
|
||||
// Write PID file atomically
|
||||
if err := s.pidFile.Write(); err != nil {
|
||||
// Write PID file atomically with the child's PID
|
||||
if err := s.pidFile.WritePID(pid); err != nil {
|
||||
// Failed to write PID file, kill the process
|
||||
cmd.Process.Kill()
|
||||
logFile.Close()
|
||||
return fmt.Errorf("failed to write PID file: %w", err)
|
||||
}
|
||||
|
||||
// Verify the child process is actually running
|
||||
// This prevents race conditions where status is checked immediately
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
if !s.pidFile.IsProcessRunning() {
|
||||
// Child process died immediately, likely a startup error
|
||||
s.pidFile.Remove()
|
||||
logFile.Close()
|
||||
return fmt.Errorf("gateway process failed to start (check log file: %s)", s.logConfig.Path)
|
||||
}
|
||||
|
||||
// Update state
|
||||
s.state.SetPID(pid)
|
||||
s.state.SetStartTime(time.Now())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue