Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. // This code is highly inspired by endless go
  5. package graceful
  6. import (
  7. "crypto/tls"
  8. "io/ioutil"
  9. "net"
  10. "os"
  11. "strings"
  12. "sync"
  13. "sync/atomic"
  14. "syscall"
  15. "time"
  16. "code.gitea.io/gitea/modules/log"
  17. )
  18. var (
  19. // DefaultReadTimeOut default read timeout
  20. DefaultReadTimeOut time.Duration
  21. // DefaultWriteTimeOut default write timeout
  22. DefaultWriteTimeOut time.Duration
  23. // DefaultMaxHeaderBytes default max header bytes
  24. DefaultMaxHeaderBytes int
  25. )
  26. func init() {
  27. DefaultMaxHeaderBytes = 0 // use http.DefaultMaxHeaderBytes - which currently is 1 << 20 (1MB)
  28. }
  29. // ServeFunction represents a listen.Accept loop
  30. type ServeFunction = func(net.Listener) error
  31. // Server represents our graceful server
  32. type Server struct {
  33. network string
  34. address string
  35. listener net.Listener
  36. wg sync.WaitGroup
  37. state state
  38. lock *sync.RWMutex
  39. BeforeBegin func(network, address string)
  40. OnShutdown func()
  41. }
  42. // NewServer creates a server on network at provided address
  43. func NewServer(network, address string) *Server {
  44. if GetManager().IsChild() {
  45. log.Info("Restarting new server: %s:%s on PID: %d", network, address, os.Getpid())
  46. } else {
  47. log.Info("Starting new server: %s:%s on PID: %d", network, address, os.Getpid())
  48. }
  49. srv := &Server{
  50. wg: sync.WaitGroup{},
  51. state: stateInit,
  52. lock: &sync.RWMutex{},
  53. network: network,
  54. address: address,
  55. }
  56. srv.BeforeBegin = func(network, addr string) {
  57. log.Debug("Starting server on %s:%s (PID: %d)", network, addr, syscall.Getpid())
  58. }
  59. return srv
  60. }
  61. // ListenAndServe listens on the provided network address and then calls Serve
  62. // to handle requests on incoming connections.
  63. func (srv *Server) ListenAndServe(serve ServeFunction) error {
  64. go srv.awaitShutdown()
  65. l, err := GetListener(srv.network, srv.address)
  66. if err != nil {
  67. log.Error("Unable to GetListener: %v", err)
  68. return err
  69. }
  70. srv.listener = newWrappedListener(l, srv)
  71. srv.BeforeBegin(srv.network, srv.address)
  72. return srv.Serve(serve)
  73. }
  74. // ListenAndServeTLS listens on the provided network address and then calls
  75. // Serve to handle requests on incoming TLS connections.
  76. //
  77. // Filenames containing a certificate and matching private key for the server must
  78. // be provided. If the certificate is signed by a certificate authority, the
  79. // certFile should be the concatenation of the server's certificate followed by the
  80. // CA's certificate.
  81. func (srv *Server) ListenAndServeTLS(certFile, keyFile string, serve ServeFunction) error {
  82. config := &tls.Config{}
  83. if config.NextProtos == nil {
  84. config.NextProtos = []string{"http/1.1"}
  85. }
  86. config.Certificates = make([]tls.Certificate, 1)
  87. certPEMBlock, err := ioutil.ReadFile(certFile)
  88. if err != nil {
  89. log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, err)
  90. return err
  91. }
  92. keyPEMBlock, err := ioutil.ReadFile(keyFile)
  93. if err != nil {
  94. log.Error("Failed to load https key file %s for %s:%s: %v", keyFile, srv.network, srv.address, err)
  95. return err
  96. }
  97. config.Certificates[0], err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
  98. if err != nil {
  99. log.Error("Failed to create certificate from cert file %s and key file %s for %s:%s: %v", certFile, keyFile, srv.network, srv.address, err)
  100. return err
  101. }
  102. return srv.ListenAndServeTLSConfig(config, serve)
  103. }
  104. // ListenAndServeTLSConfig listens on the provided network address and then calls
  105. // Serve to handle requests on incoming TLS connections.
  106. func (srv *Server) ListenAndServeTLSConfig(tlsConfig *tls.Config, serve ServeFunction) error {
  107. go srv.awaitShutdown()
  108. tlsConfig.MinVersion = tls.VersionTLS12
  109. l, err := GetListener(srv.network, srv.address)
  110. if err != nil {
  111. log.Error("Unable to get Listener: %v", err)
  112. return err
  113. }
  114. wl := newWrappedListener(l, srv)
  115. srv.listener = tls.NewListener(wl, tlsConfig)
  116. srv.BeforeBegin(srv.network, srv.address)
  117. return srv.Serve(serve)
  118. }
  119. // Serve accepts incoming HTTP connections on the wrapped listener l, creating a new
  120. // service goroutine for each. The service goroutines read requests and then call
  121. // handler to reply to them. Handler is typically nil, in which case the
  122. // DefaultServeMux is used.
  123. //
  124. // In addition to the standard Serve behaviour each connection is added to a
  125. // sync.Waitgroup so that all outstanding connections can be served before shutting
  126. // down the server.
  127. func (srv *Server) Serve(serve ServeFunction) error {
  128. defer log.Debug("Serve() returning... (PID: %d)", syscall.Getpid())
  129. srv.setState(stateRunning)
  130. GetManager().RegisterServer()
  131. err := serve(srv.listener)
  132. log.Debug("Waiting for connections to finish... (PID: %d)", syscall.Getpid())
  133. srv.wg.Wait()
  134. srv.setState(stateTerminate)
  135. GetManager().ServerDone()
  136. // use of closed means that the listeners are closed - i.e. we should be shutting down - return nil
  137. if err == nil || strings.Contains(err.Error(), "use of closed") || strings.Contains(err.Error(), "http: Server closed") {
  138. return nil
  139. }
  140. return err
  141. }
  142. func (srv *Server) getState() state {
  143. srv.lock.RLock()
  144. defer srv.lock.RUnlock()
  145. return srv.state
  146. }
  147. func (srv *Server) setState(st state) {
  148. srv.lock.Lock()
  149. defer srv.lock.Unlock()
  150. srv.state = st
  151. }
  152. type filer interface {
  153. File() (*os.File, error)
  154. }
  155. type wrappedListener struct {
  156. net.Listener
  157. stopped bool
  158. server *Server
  159. }
  160. func newWrappedListener(l net.Listener, srv *Server) *wrappedListener {
  161. return &wrappedListener{
  162. Listener: l,
  163. server: srv,
  164. }
  165. }
  166. func (wl *wrappedListener) Accept() (net.Conn, error) {
  167. var c net.Conn
  168. // Set keepalive on TCPListeners connections.
  169. if tcl, ok := wl.Listener.(*net.TCPListener); ok {
  170. tc, err := tcl.AcceptTCP()
  171. if err != nil {
  172. return nil, err
  173. }
  174. _ = tc.SetKeepAlive(true) // see http.tcpKeepAliveListener
  175. _ = tc.SetKeepAlivePeriod(3 * time.Minute) // see http.tcpKeepAliveListener
  176. c = tc
  177. } else {
  178. var err error
  179. c, err = wl.Listener.Accept()
  180. if err != nil {
  181. return nil, err
  182. }
  183. }
  184. closed := int32(0)
  185. c = wrappedConn{
  186. Conn: c,
  187. server: wl.server,
  188. closed: &closed,
  189. }
  190. wl.server.wg.Add(1)
  191. return c, nil
  192. }
  193. func (wl *wrappedListener) Close() error {
  194. if wl.stopped {
  195. return syscall.EINVAL
  196. }
  197. wl.stopped = true
  198. return wl.Listener.Close()
  199. }
  200. func (wl *wrappedListener) File() (*os.File, error) {
  201. // returns a dup(2) - FD_CLOEXEC flag *not* set so the listening socket can be passed to child processes
  202. return wl.Listener.(filer).File()
  203. }
  204. type wrappedConn struct {
  205. net.Conn
  206. server *Server
  207. closed *int32
  208. }
  209. func (w wrappedConn) Close() error {
  210. if atomic.CompareAndSwapInt32(w.closed, 0, 1) {
  211. defer func() {
  212. if err := recover(); err != nil {
  213. select {
  214. case <-GetManager().IsHammer():
  215. // Likely deadlocked request released at hammertime
  216. log.Warn("Panic during connection close! %v. Likely there has been a deadlocked request which has been released by forced shutdown.", err)
  217. default:
  218. log.Error("Panic during connection close! %v", err)
  219. }
  220. }
  221. }()
  222. w.server.wg.Done()
  223. }
  224. return w.Conn.Close()
  225. }