api/worker, koji: fix race condition when using multiple listeners

When remote worker socket was enabled, this was happening:

e := echo.New()

go func() {
    e.Listener = listener1
    e.Start("")
}()

e.Listener = listener2
e.Start("")

Yeah, this is a race condition. None of the echo's Start methods cannot safely
handle multiple listeners.

This commit fixes this issue by using Echo only as a router for standard
http.Server which handles multiple listeners in a non-racy way.
This commit is contained in:
Ondřej Budai 2020-09-23 07:40:33 +02:00
parent 2370de7a4b
commit 03768e5f18
2 changed files with 23 additions and 17 deletions

View file

@ -24,7 +24,7 @@ import (
// Server represents the state of the koji Server
type Server struct {
echo *echo.Echo
server *http.Server
workers *worker.Server
rpmMetadata rpmmd.RPMMD
distros *distro.Registry
@ -40,20 +40,23 @@ func NewServer(logger *log.Logger, workers *worker.Server, rpmMetadata rpmmd.RPM
kojiServers: kojiServers,
}
s.echo = echo.New()
s.echo.Binder = binder{}
s.echo.StdLogger = logger
e := echo.New()
e.Binder = binder{}
e.StdLogger = logger
api.RegisterHandlers(s.echo, &apiHandlers{s})
api.RegisterHandlers(e, &apiHandlers{s})
s.server = &http.Server{
ErrorLog: logger,
Handler: e,
}
return s
}
// Serve serves the koji API over the provided listener socket
func (s *Server) Serve(listener net.Listener) error {
s.echo.Listener = listener
err := s.echo.Start("")
err := s.server.Serve(listener)
if err != nil && err != http.ErrServerClosed {
return err
}

View file

@ -27,7 +27,7 @@ import (
type Server struct {
jobs jobqueue.JobQueue
echo *echo.Echo
server *http.Server
artifactsDir string
// Currently running jobs. Workers are not handed job ids, but
@ -61,19 +61,22 @@ func NewServer(logger *log.Logger, jobs jobqueue.JobQueue, artifactsDir string)
running: make(map[uuid.UUID]uuid.UUID),
}
s.echo = echo.New()
s.echo.Binder = binder{}
s.echo.StdLogger = logger
e := echo.New()
e.Binder = binder{}
e.StdLogger = logger
api.RegisterHandlers(s.echo, &apiHandlers{s})
api.RegisterHandlers(e, &apiHandlers{s})
s.server = &http.Server{
ErrorLog: logger,
Handler: e,
}
return s
}
func (s *Server) Serve(listener net.Listener) error {
s.echo.Listener = listener
err := s.echo.Start("")
err := s.server.Serve(listener)
if err != nil && err != http.ErrServerClosed {
return err
}
@ -82,7 +85,7 @@ func (s *Server) Serve(listener net.Listener) error {
}
func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
s.echo.ServeHTTP(writer, request)
s.server.Handler.ServeHTTP(writer, request)
}
func (s *Server) Enqueue(manifest distro.Manifest, targets []*target.Target) (uuid.UUID, error) {