cleanupOrphanedProcesses finds and kills xray processes that are: 1. Zombie processes (orphaned from their parent) 2. Processes where the node itself is the parent (PPID matches node PID)
()
| 383 | // 1. Zombie processes (orphaned from their parent) |
| 384 | // 2. Processes where the node itself is the parent (PPID matches node PID) |
| 385 | func (c *Core) cleanupOrphanedProcesses() error { |
| 386 | processes, err := findXrayProcesses(c.executablePath) |
| 387 | if err != nil { |
| 388 | return fmt.Errorf("failed to find xray processes: %w", err) |
| 389 | } |
| 390 | |
| 391 | currentPID := 0 |
| 392 | if c.process != nil && c.process.Process != nil { |
| 393 | currentPID = c.process.Process.Pid |
| 394 | } |
| 395 | |
| 396 | // Get current node process PID |
| 397 | nodePID := os.Getpid() |
| 398 | |
| 399 | killedCount := 0 |
| 400 | for _, procInfo := range processes { |
| 401 | if procInfo.PID == currentPID { |
| 402 | continue |
| 403 | } |
| 404 | |
| 405 | // Only clean up processes we own (parented by this node process) |
| 406 | // or zombies that have been reparented to init (no real parent). |
| 407 | kill := false |
| 408 | reason := "" |
| 409 | if procInfo.IsZombie && (procInfo.PPID == 0 || procInfo.PPID == 1) { |
| 410 | kill = true |
| 411 | reason = "zombie xray process without parent" |
| 412 | } else if procInfo.PPID == nodePID { |
| 413 | kill = true |
| 414 | reason = fmt.Sprintf("orphaned xray process with node as parent (PPID: %d)", procInfo.PPID) |
| 415 | } |
| 416 | |
| 417 | if !kill { |
| 418 | continue |
| 419 | } |
| 420 | |
| 421 | log.Printf("%s %d (PPID: %d), killing it", reason, procInfo.PID, procInfo.PPID) |
| 422 | if err := killProcessTree(procInfo.PID); err != nil { |
| 423 | log.Printf("warning: failed to kill orphaned process %d: %v", procInfo.PID, err) |
| 424 | } else { |
| 425 | killedCount++ |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | if killedCount > 0 { |
| 430 | log.Printf("cleaned up %d orphaned xray process(es)", killedCount) |
| 431 | } |
| 432 | |
| 433 | return nil |
| 434 | } |
no test coverage detected