Fix 8 bugs in proxy + exclude log files from git#40
Conversation
… order, needclose) Agent-Logs-Url: https://github.com/esrrhs/spp/sessions/c9b7bfc7-d3e2-45dd-8734-77c65a3abdef Co-authored-by: esrrhs <4083816+esrrhs@users.noreply.github.com>
Agent-Logs-Url: https://github.com/esrrhs/spp/sessions/518cdc91-076d-40dd-b8aa-81d8c6a10de5 Co-authored-by: esrrhs <4083816+esrrhs@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses multiple runtime correctness issues in the proxy implementation (primarily concurrency safety and argument validation) and improves repo hygiene by ignoring log files.
Changes:
- Make
ProxyConn.actived/pingedand ping/pong flags atomic to reduce data races; adjust message length checks and reorder CRC-check vs dispatch inrecvFrom. - Fix a client connection lifecycle issue (
needcloseoniniServicefailure) and correct a client thread-group name typo. - Prevent CLI out-of-bounds panics by validating flag slice lengths before indexing; ignore
*.login git.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
proxy/common.go |
Switches activity/heartbeat counters and ping/pong flags to atomic operations; adjusts frame length checks and recv ordering. |
proxy/inputer.go |
Uses atomic increment for sonny.actived to avoid races across goroutines. |
proxy/outputer.go |
Uses atomic increment for sonny.actived to avoid races across goroutines. |
proxy/client.go |
Fixes thread group name typo and ensures failed service init triggers connection close. |
main.go |
Validates slice lengths before indexing into CLI flag arrays to avoid panics. |
.gitignore |
Adds *.log to prevent committed log artifacts. |
Comments suppressed due to low confidence (1)
proxy/common.go:281
pongtimeis written inprocessPingand read here to populate a PONG frame, but it’s accessed via plain pointer dereference. SincesendToruns concurrently withprocessPing, this is still a data race even after makingpongflagatomic. Useatomic.StoreInt64inprocessPingandatomic.LoadInt64here (and keeppongtime64-bit aligned) to make the handoff race-free.
f = &ProxyFrame{}
f.Type = FRAME_TYPE_PONG
f.PongFrame = &PongFrame{}
f.PongFrame.Time = *pongtime
} else {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if atomic.LoadInt32(pingflag) > 0 { | ||
| atomic.StoreInt32(pingflag, 0) | ||
| f = &ProxyFrame{} | ||
| f.Type = FRAME_TYPE_PING | ||
| f.PingFrame = &PingFrame{} | ||
| f.PingFrame.Time = time.Now().UnixNano() | ||
| } else if *pongflag > 0 { | ||
| *pongflag = 0 | ||
| } else if atomic.LoadInt32(pongflag) > 0 { | ||
| atomic.StoreInt32(pongflag, 0) |
There was a problem hiding this comment.
pingflag / pongflag clearing uses atomic.LoadInt32(...) > 0 followed by atomic.StoreInt32(..., 0). If another goroutine increments the flag between the load and store, that increment can be lost, causing missed PING/PONG sends. Consider using atomic.SwapInt32(flag, 0) (or a CAS loop) so you clear the flag and observe the previous value atomically.
| type ProxyConn struct { | ||
| conn network.Conn | ||
| established bool | ||
| sendch *common.Channel // *ProxyFrame | ||
| recvch *common.Channel // *ProxyFrame | ||
| actived int | ||
| pinged int | ||
| actived int32 | ||
| pinged int32 | ||
| id string | ||
| needclose bool | ||
| } |
There was a problem hiding this comment.
ProxyConn.actived / pinged were made atomic, but established and needclose are still plain bool fields that are written and read by multiple goroutines (e.g., login/open handlers vs checkPingActive/checkNeedClose). This remains a data race in Go. Consider converting them to int32 guarded by sync/atomic, or protecting the whole connection state with a mutex.
Multiple bugs across
main.go,proxy/common.go,proxy/client.go,proxy/inputer.go, andproxy/outputer.go, plus a committed log file.Bug Fixes
main.go): Slice length equality check ran after indexing intofromaddr/toaddr/proxyproto— reordered to validate lengths firstcommon.go):uint32 msglen <= 0is alwaysfalse— changed to== 0in bothrecvFromandsendTocommon.go,inputer.go,outputer.go):pingflag/pongflagmixed plain pointer dereference withatomic.Addacross goroutines — replaced all reads/writes withatomic.Load/atomic.StoreProxyConn.pingedandProxyConn.activedaccessed unsynchronized from multiple goroutines — changed both fields toint32and guarded all accesses withsync/atomiccommon.go): InrecvFrom, CRC validation ran afterrecvch.Write(f), so corrupt frames were already consumed before detection — moved check before the writeclient.go):processLoginRspreturned without settingserverconn.needclose = truewheniniServicefailed, leaving the connection openclient.go): Thread group name"Clent"→"Client"Git Hygiene
*.logto.gitignoreproxy/default_DEBUG_2026-04-10.logfrom the index viagit rm --cached