@@ -36,6 +36,8 @@ type Server struct {
3636 wg sync.WaitGroup
3737 state state
3838 lock * sync.RWMutex
39+ connections map [* wrappedConn ]struct {}
40+ connectionsLock sync.RWMutex
3941 BeforeBegin func (network , address string )
4042 OnShutdown func ()
4143 PerWriteTimeout time.Duration
@@ -53,6 +55,7 @@ func NewServer(network, address, name string) *Server {
5355 wg : sync.WaitGroup {},
5456 state : stateInit ,
5557 lock : & sync.RWMutex {},
58+ connections : make (map [* wrappedConn ]struct {}),
5659 network : network ,
5760 address : address ,
5861 PerWriteTimeout : setting .PerWriteTimeout ,
@@ -178,6 +181,21 @@ func (srv *Server) setState(st state) {
178181 srv .state = st
179182}
180183
184+ // closeAllConnections forcefully closes all active connections
185+ func (srv * Server ) closeAllConnections () {
186+ srv .connectionsLock .Lock ()
187+ connections := make ([]* wrappedConn , 0 , len (srv .connections ))
188+ for conn := range srv .connections {
189+ connections = append (connections , conn )
190+ }
191+ srv .connectionsLock .Unlock ()
192+
193+ // Close all connections outside the lock to avoid deadlock
194+ for _ , conn := range connections {
195+ _ = conn .Conn .Close () // Force close the underlying connection
196+ }
197+ }
198+
181199type filer interface {
182200 File () (* os.File , error )
183201}
@@ -216,16 +234,20 @@ func (wl *wrappedListener) Accept() (net.Conn, error) {
216234
217235 closed := int32 (0 )
218236
219- c = & wrappedConn {
220- Conn : c ,
221- server : wl .server ,
222- closed : & closed ,
223- perWriteTimeout : wl .server .PerWriteTimeout ,
224- perWritePerKbTimeout : wl .server .PerWritePerKbTimeout ,
237+ wc := & wrappedConn {
238+ Conn : c ,
239+ server : wl .server ,
240+ closed : & closed ,
225241 }
226242
227243 wl .server .wg .Add (1 )
228- return c , nil
244+
245+ // Track the connection
246+ wl .server .connectionsLock .Lock ()
247+ wl .server .connections [wc ] = struct {}{}
248+ wl .server .connectionsLock .Unlock ()
249+
250+ return wc , nil
229251}
230252
231253func (wl * wrappedListener ) Close () error {
@@ -244,17 +266,15 @@ func (wl *wrappedListener) File() (*os.File, error) {
244266
245267type wrappedConn struct {
246268 net.Conn
247- server * Server
248- closed * int32
249- deadline time.Time
250- perWriteTimeout time.Duration
251- perWritePerKbTimeout time.Duration
269+ server * Server
270+ closed * int32
271+ deadline time.Time
252272}
253273
254274func (w * wrappedConn ) Write (p []byte ) (n int , err error ) {
255- if w .perWriteTimeout > 0 {
256- minTimeout := time .Duration (len (p )/ 1024 ) * w .perWritePerKbTimeout
257- minDeadline := time .Now ().Add (minTimeout ).Add (w .perWriteTimeout )
275+ if w .server . PerWriteTimeout > 0 {
276+ minTimeout := time .Duration (len (p )/ 1024 ) * w .server . PerWritePerKbTimeout
277+ minDeadline := time .Now ().Add (minTimeout ).Add (w .server . PerWriteTimeout )
258278
259279 w .deadline = w .deadline .Add (minTimeout )
260280 if minDeadline .After (w .deadline ) {
@@ -278,6 +298,12 @@ func (w *wrappedConn) Close() error {
278298 }
279299 }
280300 }()
301+
302+ // Remove from tracked connections
303+ w .server .connectionsLock .Lock ()
304+ delete (w .server .connections , w )
305+ w .server .connectionsLock .Unlock ()
306+
281307 w .server .wg .Done ()
282308 }
283309 return w .Conn .Close ()
0 commit comments