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
Post a Comment