go - http.Server Serve method hangs when calling Shutdown immediately -


i have issue go's http.server, i'm embedding in struct supposed control server startup , shutdown. struct looks this:

type httplisten struct {     consumers []pipeline.consumer     cfg       httplistenconfig     srv       *http.server     logger    log.logger     wg        *sync.waitgroup     mu        sync.mutex     state     state } 

the issue in test code, call struct's start() method (which in turn runs serve() method on http.server), check few vars, , call stop(), whitch shutdown()s server , waits http.server exit (return err serve() method).

now, reason, serve() method seems hang on waitgroup.wait(), when try shutdown server after starting. when add short pause (tried 100ms), or when running tests race detector, works fine.

not sure if matters, there no incoming requests between calling serve() , shutdown().

edit: link playground minimal example. if comment out time.sleep call, program hangs.

here relevant code 2 methods:

func (h *httplisten) start() error {      h.logger.log("msg", "starting httplisten input")      addr := h.cfg.listenaddr     ln, err := net.listen("tcp", addr)     if err != nil {         h.logger.log("msg", "failed create listener on tcp/"+addr+": "+err.error())         h.setstate(statefailed)         return err     }      h.wg.add(1)     go func() {          defer h.wg.done()         err := h.srv.serve(ln)         h.logger.log("msg", "http server stopped: "+err.error())      }()      h.setstate(statestarted)     h.logger.log("msg", "httplisten input started")      return nil  } 

stop method:

func (h *httplisten) stop() error {      h.logger.log("msg", "stopping httplisten input")      ctx, cancel := context.withtimeout(context.background(), time.second*10)     defer cancel()      if err := h.srv.shutdown(ctx); err != nil {         h.logger.log("msg", "http server shutdown deadline expired")     }      h.wg.wait()      h.setstate(statestopped)     h.logger.log("msg", "httplisten input stopped")      return nil } 

log output:

kwz@cyclone ~/s/stblogd> go test -v ./pkg/pipeline/input/ -run testhttplisten_startstop === run   testhttplisten_startstop msg="starting httplisten input" msg="httplisten input started" msg="stopping httplisten input" ... hangs indefinitely 

log output when running tests race detector:

kwz@cyclone ~/s/stblogd> go test -race -v ./pkg/pipeline/input/ -run testhttplisten_startstop === run   testhttplisten_startstop msg="starting httplisten input" msg="httplisten input started" msg="stopping httplisten input" msg="http server stopped: http: server closed" msg="httplisten input stopped" --- pass: testhttplisten_startstop (0.00s) pass ok      stblogd/pkg/pipeline/input      1.007s 

i'm tempted slap short delay on test , call day, know why behaves this.

this known issue, see thread:

https://github.com/golang/go/issues/20239

hopefully fix sounds adding short delay in test simplest solution - doesn't come in real world use because won't trigger shutdown after starting.


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -