@@ -13,6 +13,7 @@ import (
1313 "strings"
1414 "sync"
1515 "sync/atomic"
16+ "syscall"
1617 "time"
1718
1819 "github.com/bwmarrin/discordgo"
@@ -1274,12 +1275,51 @@ func FactWhisper(player, format string, args ...interface{}) {
12741275}
12751276
12761277func WaitFactQuit (waiting bool ) {
1278+ checkProcessAlive := func () bool {
1279+ cmd := glob .FactorioCmd
1280+ if cmd == nil || cmd .Process == nil {
1281+ return false
1282+ }
1283+ if cmd .ProcessState != nil && cmd .ProcessState .Exited () {
1284+ return false
1285+ }
1286+ if err := cmd .Process .Signal (syscall .Signal (0 )); err != nil {
1287+ return false
1288+ }
1289+ // When cmd.Wait() hasn't been called yet, an exited child can remain as a zombie
1290+ // and still answer signal 0 successfully. Treat zombies as not alive.
1291+ if data , err := os .ReadFile (fmt .Sprintf ("/proc/%d/stat" , cmd .Process .Pid )); err == nil {
1292+ if s := string (data ); s != "" {
1293+ if idx := strings .LastIndex (s , ") " ); idx >= 0 && len (s ) > idx + 2 && s [idx + 2 ] == 'Z' {
1294+ return false
1295+ }
1296+ }
1297+ }
1298+ return true
1299+ }
1300+
12771301 if waiting {
1302+ started := time .Now ()
12781303 for FactIsRunning && FactorioBooted && glob .ServerRunning {
1304+ // "Goodbye" log parsing normally clears FactIsRunning. If that line is missed,
1305+ // fall back to the actual process state so update/reboot flows do not hang forever.
1306+ if ! checkProcessAlive () {
1307+ cwlog .DoLogCW ("WaitFactQuit: Factorio state was stale; process is no longer alive." )
1308+ SetFactRunning (false , false )
1309+ break
1310+ }
1311+ if time .Since (started ) > 2 * time .Minute {
1312+ cwlog .DoLogCW ("WaitFactQuit: timed out after 2m waiting for Factorio to quit." )
1313+ break
1314+ }
12791315 time .Sleep (time .Millisecond * 100 )
12801316 }
12811317 } else {
12821318 for x := 0 ; x < constants .MaxFactorioCloseWait && FactIsRunning && FactorioBooted && glob .ServerRunning ; x ++ {
1319+ if ! checkProcessAlive () {
1320+ SetFactRunning (false , false )
1321+ break
1322+ }
12831323 time .Sleep (time .Millisecond * 100 )
12841324 }
12851325 }
0 commit comments