Skip to content

Commit 42dfd7e

Browse files
committed
use counter instead of list for conn
1 parent e7c50a8 commit 42dfd7e

File tree

2 files changed

+13
-62
lines changed

2 files changed

+13
-62
lines changed

cmd/web.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,6 @@ func serveInstalled(c *cli.Command) error {
169169

170170
showWebStartupMessage("Prepare to run web server")
171171

172-
// FIXME: remove it if it doesn't really help
173-
// Check for shutdown signal during startup
174-
/*
175-
select {
176-
case <-graceful.GetManager().IsShutdown():
177-
log.Info("Shutdown signal received during startup, aborting server start")
178-
<-graceful.GetManager().Done()
179-
log.Info("PID: %d Gitea Web Finished", os.Getpid())
180-
return nil
181-
default:
182-
}
183-
*/
184-
185172
if setting.AppWorkPathMismatch {
186173
log.Error("WORK_PATH from config %q doesn't match other paths from environment variables or command arguments. "+
187174
"Only WORK_PATH in config should be set and used. Please make sure the path in config file is correct, "+
@@ -238,19 +225,6 @@ func serveInstalled(c *cli.Command) error {
238225

239226
gtprof.EnableBuiltinTracer(util.Iif(setting.IsProd, 2000*time.Millisecond, 100*time.Millisecond))
240227

241-
// FIXME: remove it if it doesn't really help
242-
// Check for shutdown signal before starting web server
243-
/*
244-
select {
245-
case <-graceful.GetManager().IsShutdown():
246-
log.Info("Shutdown signal received before starting web server, aborting")
247-
<-graceful.GetManager().Done()
248-
log.Info("PID: %d Gitea Web Finished", os.Getpid())
249-
return nil
250-
default:
251-
}
252-
*/
253-
254228
// Set up Chi routes
255229
webRoutes := routers.NormalRoutes()
256230
err := listen(webRoutes, true)

modules/graceful/server.go

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package graceful
77

88
import (
9-
"container/list"
109
"crypto/tls"
1110
"net"
1211
"os"
@@ -34,11 +33,9 @@ type Server struct {
3433
address string
3534
listener net.Listener
3635

37-
lock sync.RWMutex
38-
state state
39-
// FIXME: actually we do not need to record the whole list, just a counter should be enough
40-
// Because the connections will be closed by OS, no need to track them one by one.
41-
connList *list.List
36+
lock sync.RWMutex
37+
state state
38+
connCounter int64
4239
connEmptyCond *sync.Cond
4340

4441
BeforeBegin func(network, address string)
@@ -56,7 +53,6 @@ func NewServer(network, address, name string) *Server {
5653
}
5754
srv := &Server{
5855
state: stateInit,
59-
connList: list.New(),
6056
network: network,
6157
address: address,
6258
PerWriteTimeout: setting.PerWriteTimeout,
@@ -185,7 +181,7 @@ func (srv *Server) setState(st state) {
185181

186182
func (srv *Server) waitForActiveConnections() {
187183
srv.lock.Lock()
188-
for srv.connList.Len() > 0 {
184+
for srv.connCounter > 0 {
189185
srv.connEmptyCond.Wait()
190186
}
191187
srv.lock.Unlock()
@@ -200,42 +196,28 @@ func (srv *Server) wrapConnection(c net.Conn) (net.Conn, error) {
200196
return nil, syscall.EINVAL // same as AcceptTCP
201197
}
202198

203-
wc := &wrappedConn{Conn: c, server: srv}
204-
wc.listElem = srv.connList.PushBack(wc)
205-
return wc, nil
199+
srv.connCounter++
200+
return &wrappedConn{Conn: c, server: srv}, nil
206201
}
207202

208-
func (srv *Server) removeConnection(conn *wrappedConn) {
203+
func (srv *Server) removeConnection(_ *wrappedConn) {
209204
srv.lock.Lock()
210205
defer srv.lock.Unlock()
211206

212-
if conn.listElem == nil {
213-
return
214-
}
215-
srv.connList.Remove(conn.listElem)
216-
if srv.connList.Len() == 0 {
207+
srv.connCounter--
208+
if srv.connCounter <= 0 {
217209
srv.connEmptyCond.Broadcast()
218210
}
219211
}
220212

221213
// closeAllConnections forcefully closes all active connections
222214
func (srv *Server) closeAllConnections() {
223215
srv.lock.Lock()
224-
if srv.connList.Len() > 0 {
225-
log.Warn("Forcefully closing all %d connections", srv.connList.Len())
226-
}
227-
conns := make([]*wrappedConn, 0, srv.connList.Len())
228-
for e := srv.connList.Front(); e != nil; e = e.Next() {
229-
conn := e.Value.(*wrappedConn)
230-
conn.listElem = nil // mark as removed, will close it later to avoid deadlock of "server.lock"
231-
conns = append(conns, conn)
216+
if srv.connCounter > 0 {
217+
log.Warn("After graceful shutdown period, %d connections are still active. Forcefully close.", srv.connCounter)
218+
srv.connCounter = 0 // OS will close all the connections after the process exits, so we just assume there is no active connection now
232219
}
233-
srv.connList = list.New()
234220
srv.lock.Unlock()
235-
236-
for _, conn := range conns {
237-
_ = conn.Close() // do real close outside of lock
238-
}
239221
srv.connEmptyCond.Broadcast()
240222
}
241223

@@ -262,7 +244,7 @@ func newWrappedListener(l net.Listener, srv *Server) *wrappedListener {
262244

263245
func (wl *wrappedListener) Accept() (c net.Conn, err error) {
264246
if tcl, ok := wl.Listener.(*net.TCPListener); ok {
265-
// Set keepalive on TCPListeners connections if possible, http.tcpKeepAliveListener
247+
// Set keepalive on TCPListeners connections if possible, see http.tcpKeepAliveListener
266248
tc, err := tcl.AcceptTCP()
267249
if err != nil {
268250
return nil, err
@@ -287,11 +269,6 @@ func (wl *wrappedListener) File() (*os.File, error) {
287269

288270
type wrappedConn struct {
289271
net.Conn
290-
291-
// listElem is protected by the server's lock (used by the server to remove conn itself from the list)
292-
// nil means it has been removed
293-
listElem *list.Element
294-
295272
server *Server
296273
deadline time.Time
297274
}

0 commit comments

Comments
 (0)