fix potential panic on http server close (#496)

This commit is contained in:
Brian Goff
2019-01-15 10:37:06 -08:00
committed by GitHub
parent fe0170fc5c
commit ac0551e8c2
2 changed files with 25 additions and 20 deletions

39
http.go
View File

@@ -44,11 +44,19 @@ func loadTLSConfig(certPath, keyPath string) (*tls.Config, error) {
}, nil }, nil
} }
func setupHTTPServer(ctx context.Context, cfg *apiServerConfig) (io.Closer, io.Closer, error) { func setupHTTPServer(ctx context.Context, cfg *apiServerConfig) (cancel func(), retErr error) {
var ( var closers []io.Closer
podS *http.Server cancel = func() {
metricsS *http.Server for _, c := range closers {
) c.Close()
}
}
defer func() {
if retErr != nil {
cancel()
}
}()
if cfg.CertPath == "" || cfg.KeyPath == "" { if cfg.CertPath == "" || cfg.KeyPath == "" {
log.G(ctx). log.G(ctx).
WithField("certPath", cfg.CertPath). WithField("certPath", cfg.CertPath).
@@ -57,21 +65,22 @@ func setupHTTPServer(ctx context.Context, cfg *apiServerConfig) (io.Closer, io.C
} else { } else {
tlsCfg, err := loadTLSConfig(cfg.CertPath, cfg.KeyPath) tlsCfg, err := loadTLSConfig(cfg.CertPath, cfg.KeyPath)
if err != nil { if err != nil {
return nil, nil, err return nil, err
} }
l, err := tls.Listen("tcp", cfg.Addr, tlsCfg) l, err := tls.Listen("tcp", cfg.Addr, tlsCfg)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "error setting up listener for pod http server") return nil, errors.Wrap(err, "error setting up listener for pod http server")
} }
mux := http.NewServeMux() mux := http.NewServeMux()
vkubelet.AttachPodRoutes(p, mux) vkubelet.AttachPodRoutes(p, mux)
podS = &http.Server{ s := &http.Server{
Handler: mux, Handler: mux,
TLSConfig: tlsCfg, TLSConfig: tlsCfg,
} }
go serveHTTP(ctx, podS, l, "pods") go serveHTTP(ctx, s, l, "pods")
closers = append(closers, s)
} }
if cfg.MetricsAddr == "" { if cfg.MetricsAddr == "" {
@@ -79,21 +88,19 @@ func setupHTTPServer(ctx context.Context, cfg *apiServerConfig) (io.Closer, io.C
} else { } else {
l, err := net.Listen("tcp", cfg.MetricsAddr) l, err := net.Listen("tcp", cfg.MetricsAddr)
if err != nil { if err != nil {
if l != nil { return nil, errors.Wrap(err, "could not setup listener for pod metrics http server")
podS.Close()
}
return nil, nil, errors.Wrap(err, "could not setup listenr for pod metrics http server")
} }
mux := http.NewServeMux() mux := http.NewServeMux()
vkubelet.AttachMetricsRoutes(p, mux) vkubelet.AttachMetricsRoutes(p, mux)
metricsS = &http.Server{ s := &http.Server{
Handler: mux, Handler: mux,
} }
go serveHTTP(ctx, metricsS, l, "pod metrics") go serveHTTP(ctx, s, l, "pod metrics")
closers = append(closers, s)
} }
return podS, metricsS, nil return cancel, nil
} }
func serveHTTP(ctx context.Context, s *http.Server, l net.Listener, name string) { func serveHTTP(ctx context.Context, s *http.Server, l net.Listener, name string) {

View File

@@ -108,13 +108,11 @@ This allows users to schedule kubernetes workloads on nodes that aren't running
rootContextCancel() rootContextCancel()
}() }()
c1, c2, err := setupHTTPServer(rootContext, apiConfig) cancelHTTP, err := setupHTTPServer(rootContext, apiConfig)
if err != nil { if err != nil {
log.G(rootContext).Fatal(err) log.G(rootContext).Fatal(err)
} }
defer cancelHTTP()
defer c1.Close()
defer c2.Close()
if err := vk.Run(rootContext); err != nil && errors.Cause(err) != context.Canceled { if err := vk.Run(rootContext); err != nil && errors.Cause(err) != context.Canceled {
log.G(rootContext).Fatal(err) log.G(rootContext).Fatal(err)