From 236fe841100ef0ee1feee2fa84d440ee6e74b04c Mon Sep 17 00:00:00 2001 From: GouJie <507762441@qq.com> Date: Sat, 20 Jan 2024 00:17:15 +0800 Subject: [PATCH] bugfix: Resolved a concurrency issue with ClientCounter. Previously, directly decrementing ClientCounter in multiple goroutines (ClientCounter--) could lead to data races and inconsistencies. Now, by using atomic.AddInt32(&ClientCounter, -1), we ensure safe updates to the counter, maintaining its accuracy and stability even in high concurrency scenarios. --- tcp/echo_test.go | 35 +++++++++++++++++++++++++++++++++++ tcp/server.go | 5 +++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tcp/echo_test.go b/tcp/echo_test.go index 1bc211c8..ef2bd5cc 100644 --- a/tcp/echo_test.go +++ b/tcp/echo_test.go @@ -51,3 +51,38 @@ func TestListenAndServe(t *testing.T) { closeChan <- struct{}{} time.Sleep(time.Second) } + +func TestClientCounter(t *testing.T) { + var err error + closeChan := make(chan struct{}) + listener, err := net.Listen("tcp", ":0") + if err != nil { + t.Error(err) + return + } + addr := listener.Addr().String() + go ListenAndServe(listener, MakeEchoHandler(), closeChan) + + sleepUntil := time.Now().Add(3 * time.Second) + subtime := func() time.Duration { + return sleepUntil.Sub(time.Now()) + } + + for i := 0; i < 1000; i++ { + go func() { + conn, err := net.Dial("tcp", addr) + if err != nil { + t.Errorf(err.Error()) + } + defer conn.Close() + + time.Sleep(subtime()) + }() + time.Sleep(5 * time.Microsecond) + } + + time.Sleep(3 * time.Second) + if ClientCounter != 0 { + t.Errorf("client counter error: %d", ClientCounter) + } +} diff --git a/tcp/server.go b/tcp/server.go index e381de17..b74de25d 100644 --- a/tcp/server.go +++ b/tcp/server.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "sync" + "sync/atomic" "syscall" "time" @@ -26,7 +27,7 @@ type Config struct { } // ClientCounter Record the number of clients in the current Godis server -var ClientCounter int +var ClientCounter int32 // ListenAndServeWithSignal binds port and handle requests, blocking until receive stop signal func ListenAndServeWithSignal(cfg *Config, handler tcp.Handler) error { @@ -88,7 +89,7 @@ func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan go func() { defer func() { waitDone.Done() - ClientCounter-- + atomic.AddInt32(&ClientCounter, -1) }() handler.Handle(ctx, conn) }()