fix(channelserver): eliminate data races in shutdown and session lifecycle

The channel server had several concurrency issues found by the race
detector during isolation testing:

- acceptClients could send on a closed acceptConns channel during
  shutdown, causing a panic. Replace close(acceptConns) with a done
  channel and select-based shutdown signaling in both acceptClients
  and manageSessions.
- invalidateSessions read isShuttingDown and iterated sessions without
  holding the lock. Rewrite with ticker + done channel select and
  snapshot sessions under lock before processing timeouts.
- sendLoop/recvLoop accessed global _config.ErupeConfig.LoopDelay
  which races with tests modifying the global. Use the per-server
  erupeConfig instead.
- logoutPlayer panicked on DB errors and crashed on nil DB (no-db
  test scenarios). Guard with nil check and log errors instead.
- Shutdown was not idempotent, double-calling caused double-close
  panic on done channel.

Add 5 channel isolation tests verifying independent shutdown,
listener failure, session panic recovery, cross-channel registry
after shutdown, and stage isolation.
This commit is contained in:
Houmgaor
2026-02-20 14:36:37 +01:00
parent 486be65a38
commit eab7d1fc4f
4 changed files with 260 additions and 30 deletions

View File

@@ -4,7 +4,6 @@ import (
"encoding/binary"
"encoding/hex"
"erupe-ce/common/mhfcourse"
_config "erupe-ce/config"
"fmt"
"io"
"net"
@@ -172,7 +171,7 @@ func (s *Session) sendLoop() {
s.logger.Warn("Failed to send packet", zap.Error(err))
}
}
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
time.Sleep(time.Duration(s.server.erupeConfig.LoopDelay) * time.Millisecond)
}
}
@@ -215,7 +214,7 @@ func (s *Session) recvLoop() {
return
}
s.handlePacketGroup(pkt)
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
time.Sleep(time.Duration(s.server.erupeConfig.LoopDelay) * time.Millisecond)
}
}