mirror of
https://github.com/traefik/traefik.git
synced 2025-09-20 21:31:14 +02:00
Errors on receving sigterm
This commit is contained in:
parent
86422af988
commit
fd8a64ca95
@ -12,6 +12,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -56,15 +57,19 @@ type connState struct {
|
|||||||
|
|
||||||
type httpForwarder struct {
|
type httpForwarder struct {
|
||||||
net.Listener
|
net.Listener
|
||||||
connChan chan net.Conn
|
|
||||||
errChan chan error
|
connChan chan net.Conn
|
||||||
|
errChan chan error
|
||||||
|
closeChan chan struct{}
|
||||||
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHTTPForwarder(ln net.Listener) *httpForwarder {
|
func newHTTPForwarder(ln net.Listener) *httpForwarder {
|
||||||
return &httpForwarder{
|
return &httpForwarder{
|
||||||
Listener: ln,
|
Listener: ln,
|
||||||
connChan: make(chan net.Conn),
|
connChan: make(chan net.Conn),
|
||||||
errChan: make(chan error),
|
errChan: make(chan error),
|
||||||
|
closeChan: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +81,8 @@ func (h *httpForwarder) ServeTCP(conn tcp.WriteCloser) {
|
|||||||
// Accept retrieves a served connection in ServeTCP.
|
// Accept retrieves a served connection in ServeTCP.
|
||||||
func (h *httpForwarder) Accept() (net.Conn, error) {
|
func (h *httpForwarder) Accept() (net.Conn, error) {
|
||||||
select {
|
select {
|
||||||
|
case <-h.closeChan:
|
||||||
|
return nil, errors.New("listener closed")
|
||||||
case conn := <-h.connChan:
|
case conn := <-h.connChan:
|
||||||
return conn, nil
|
return conn, nil
|
||||||
case err := <-h.errChan:
|
case err := <-h.errChan:
|
||||||
@ -83,6 +90,14 @@ func (h *httpForwarder) Accept() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes the wrapped listener and unblocks Accept.
|
||||||
|
func (h *httpForwarder) Close() error {
|
||||||
|
h.closeOnce.Do(func() {
|
||||||
|
close(h.closeChan)
|
||||||
|
})
|
||||||
|
return h.Listener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// TCPEntryPoints holds a map of TCPEntryPoint (the entrypoint names being the keys).
|
// TCPEntryPoints holds a map of TCPEntryPoint (the entrypoint names being the keys).
|
||||||
type TCPEntryPoints map[string]*TCPEntryPoint
|
type TCPEntryPoints map[string]*TCPEntryPoint
|
||||||
|
|
||||||
@ -162,8 +177,9 @@ type TCPEntryPoint struct {
|
|||||||
tracker *connectionTracker
|
tracker *connectionTracker
|
||||||
httpServer *httpServer
|
httpServer *httpServer
|
||||||
httpsServer *httpServer
|
httpsServer *httpServer
|
||||||
|
http3Server *http3server
|
||||||
http3Server *http3server
|
// inShutdown reports whether the Shutdown method has been called.
|
||||||
|
inShutdown atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPEntryPoint creates a new TCPEntryPoint.
|
// NewTCPEntryPoint creates a new TCPEntryPoint.
|
||||||
@ -172,31 +188,31 @@ func NewTCPEntryPoint(ctx context.Context, name string, config *static.EntryPoin
|
|||||||
|
|
||||||
listener, err := buildListener(ctx, name, config)
|
listener, err := buildListener(ctx, name, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error preparing server: %w", err)
|
return nil, fmt.Errorf("building listener: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rt, err := tcprouter.NewRouter()
|
rt, err := tcprouter.NewRouter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error preparing tcp router: %w", err)
|
return nil, fmt.Errorf("creating TCP router: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqDecorator := requestdecorator.New(hostResolverConfig)
|
reqDecorator := requestdecorator.New(hostResolverConfig)
|
||||||
|
|
||||||
httpServer, err := createHTTPServer(ctx, listener, config, true, reqDecorator)
|
httpServer, err := newHTTPServer(ctx, listener, config, true, reqDecorator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error preparing http server: %w", err)
|
return nil, fmt.Errorf("creating HTTP server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.SetHTTPForwarder(httpServer.Forwarder)
|
rt.SetHTTPForwarder(httpServer.Forwarder)
|
||||||
|
|
||||||
httpsServer, err := createHTTPServer(ctx, listener, config, false, reqDecorator)
|
httpsServer, err := newHTTPServer(ctx, listener, config, false, reqDecorator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error preparing https server: %w", err)
|
return nil, fmt.Errorf("creating HTTPS server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h3Server, err := newHTTP3Server(ctx, name, config, httpsServer)
|
h3Server, err := newHTTP3Server(ctx, name, config, httpsServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error preparing http3 server: %w", err)
|
return nil, fmt.Errorf("creating HTTP3 server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.SetHTTPSForwarder(httpsServer.Forwarder)
|
rt.SetHTTPSForwarder(httpsServer.Forwarder)
|
||||||
@ -226,6 +242,11 @@ func (e *TCPEntryPoint) Start(ctx context.Context) {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
conn, err := e.listener.Accept()
|
conn, err := e.listener.Accept()
|
||||||
|
// As the Shutdown method has been called, an error is expected.
|
||||||
|
// Thus, it is not necessary to log it.
|
||||||
|
if err != nil && e.inShutdown.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Send()
|
logger.Error().Err(err).Send()
|
||||||
|
|
||||||
@ -277,6 +298,8 @@ func (e *TCPEntryPoint) Start(ctx context.Context) {
|
|||||||
func (e *TCPEntryPoint) Shutdown(ctx context.Context) {
|
func (e *TCPEntryPoint) Shutdown(ctx context.Context) {
|
||||||
logger := log.Ctx(ctx)
|
logger := log.Ctx(ctx)
|
||||||
|
|
||||||
|
e.inShutdown.Store(true)
|
||||||
|
|
||||||
reqAcceptGraceTimeOut := time.Duration(e.transportConfiguration.LifeCycle.RequestAcceptGraceTimeout)
|
reqAcceptGraceTimeOut := time.Duration(e.transportConfiguration.LifeCycle.RequestAcceptGraceTimeout)
|
||||||
if reqAcceptGraceTimeOut > 0 {
|
if reqAcceptGraceTimeOut > 0 {
|
||||||
logger.Info().Msgf("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut)
|
logger.Info().Msgf("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut)
|
||||||
@ -461,6 +484,18 @@ func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoi
|
|||||||
return proxyListener, nil
|
return proxyListener, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type onceCloseListener struct {
|
||||||
|
net.Listener
|
||||||
|
|
||||||
|
once sync.Once
|
||||||
|
closeErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oc *onceCloseListener) Close() error {
|
||||||
|
oc.once.Do(func() { oc.closeErr = oc.Listener.Close() })
|
||||||
|
return oc.closeErr
|
||||||
|
}
|
||||||
|
|
||||||
func buildListener(ctx context.Context, name string, config *static.EntryPoint) (net.Listener, error) {
|
func buildListener(ctx context.Context, name string, config *static.EntryPoint) (net.Listener, error) {
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
@ -496,7 +531,7 @@ func buildListener(ctx context.Context, name string, config *static.EntryPoint)
|
|||||||
return nil, fmt.Errorf("error creating proxy protocol listener: %w", err)
|
return nil, fmt.Errorf("error creating proxy protocol listener: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listener, nil
|
return &onceCloseListener{Listener: listener}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConnectionTracker(openConnectionsGauge gokitmetrics.Gauge) *connectionTracker {
|
func newConnectionTracker(openConnectionsGauge gokitmetrics.Gauge) *connectionTracker {
|
||||||
@ -592,7 +627,7 @@ type httpServer struct {
|
|||||||
Switcher *middlewares.HTTPHandlerSwitcher
|
Switcher *middlewares.HTTPHandlerSwitcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool, reqDecorator *requestdecorator.RequestDecorator) (*httpServer, error) {
|
func newHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool, reqDecorator *requestdecorator.RequestDecorator) (*httpServer, error) {
|
||||||
if configuration.HTTP2.MaxConcurrentStreams < 0 {
|
if configuration.HTTP2.MaxConcurrentStreams < 0 {
|
||||||
return nil, errors.New("max concurrent streams value must be greater than or equal to zero")
|
return nil, errors.New("max concurrent streams value must be greater than or equal to zero")
|
||||||
}
|
}
|
||||||
@ -692,7 +727,7 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
|
|||||||
go func() {
|
go func() {
|
||||||
err := serverHTTP.Serve(listener)
|
err := serverHTTP.Serve(listener)
|
||||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("Error while starting server")
|
log.Ctx(ctx).Error().Err(err).Msg("Error while running HTTP server")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return &httpServer{
|
return &httpServer{
|
||||||
|
@ -511,7 +511,7 @@ func TestNormalizePath_malformedPercentEncoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPathOperations tests the whole behavior of normalizePath, and sanitizePath combined through the use of the createHTTPServer func.
|
// TestPathOperations tests the whole behavior of normalizePath, and sanitizePath combined through the use of the newHTTPServer func.
|
||||||
// It aims to guarantee the server entrypoint handler is secure regarding a large variety of cases that could lead to path traversal attacks.
|
// It aims to guarantee the server entrypoint handler is secure regarding a large variety of cases that could lead to path traversal attacks.
|
||||||
func TestPathOperations(t *testing.T) {
|
func TestPathOperations(t *testing.T) {
|
||||||
// Create a listener for the server.
|
// Create a listener for the server.
|
||||||
@ -525,8 +525,8 @@ func TestPathOperations(t *testing.T) {
|
|||||||
configuration := &static.EntryPoint{}
|
configuration := &static.EntryPoint{}
|
||||||
configuration.SetDefaults()
|
configuration.SetDefaults()
|
||||||
|
|
||||||
// Create the HTTP server using createHTTPServer.
|
// Create the HTTP server using newHTTPServer.
|
||||||
server, err := createHTTPServer(t.Context(), ln, configuration, false, requestdecorator.New(nil))
|
server, err := newHTTPServer(t.Context(), ln, configuration, false, requestdecorator.New(nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
server.Switcher.UpdateHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
server.Switcher.UpdateHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user