diff options
| author | Jeff Halter <868228+jhalter@users.noreply.github.com> | 2026-06-12 08:47:54 -0700 |
|---|---|---|
| committer | Jeff Halter <868228+jhalter@users.noreply.github.com> | 2026-06-12 08:47:54 -0700 |
| commit | c15f8510fbd5ccf9a122f88d6e975d1ef69e00b3 (patch) | |
| tree | 1ba7e392610637ed792d0003568cf9edb6adc526 /cmd/mobius-hotline-server | |
| parent | b2c462a3a1353f0653a5964b3a6924538ce83523 (diff) | |
Fix data races on ClientConn state, banner reload, and rate limiter growth
ClientConn's mutable session state (Flags, UserName, Icon, IdleTime,
AutoReply) was guarded inconsistently: two mutexes (FlagsMU and mu)
covered some paths while others mutated or read the fields with no
locking at all, including HandleSetClientUserInfo, HandleUpdateUser
(which writes other clients' admin flag), the login flow, the HTTP API
handlers, and the keepalive loop. Consolidate on a single mutex with
accessor methods (SetFlag/IsFlagSet/FlagBytes, SetUserName/GetUserName,
and so on) used by all production code; direct field access remains for
test construction. The idle/away logic moves into incrementIdleTime
and clearIdleAndAway helpers that report whether a notification is
needed, so SendAll is no longer called while holding the lock.
HandleRejectChatInvite also no longer appends to the username slice,
which could write past its length into the backing buffer.
The server banner is now behind Banner/SetBanner with an RWMutex: the
SIGHUP reload previously reassigned the field while banner download
goroutines read it, and nilled it when the file read failed. Reload
now keeps the previous banner on failure.
Per-IP rate limiter entries now record a last-seen time, and the
keepalive ticker evicts entries idle for over seven days, so the map
no longer grows unboundedly with each unique client IP.
Diffstat (limited to 'cmd/mobius-hotline-server')
| -rw-r--r-- | cmd/mobius-hotline-server/main.go | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/cmd/mobius-hotline-server/main.go b/cmd/mobius-hotline-server/main.go index 1c298a2..117cb2a 100644 --- a/cmd/mobius-hotline-server/main.go +++ b/cmd/mobius-hotline-server/main.go @@ -159,11 +159,12 @@ func main() { } bannerPath := path.Join(*configDir, config.BannerFile) - srv.Banner, err = os.ReadFile(bannerPath) + banner, err := os.ReadFile(bannerPath) if err != nil { slogger.Error("Error loading banner", "err", err) os.Exit(1) } + srv.SetBanner(banner) reloadFunc := func() { if err := srv.MessageBoard.(*mobius.FlatNews).Reload(); err != nil { @@ -185,11 +186,13 @@ func main() { slogger.Error("Error reloading agreement", "err", err) } - // Let's try to reload the banner + // Let's try to reload the banner. On failure, keep serving the previous banner. bannerPath := path.Join(*configDir, config.BannerFile) - srv.Banner, err = os.ReadFile(bannerPath) + banner, err := os.ReadFile(bannerPath) if err != nil { slogger.Error("Error reloading banner", "err", err) + } else { + srv.SetBanner(banner) } } |