diff options
author | Jhon Honce <jhonce@redhat.com> | 2020-02-10 14:24:10 -0700 |
---|---|---|
committer | Jhon Honce <jhonce@redhat.com> | 2020-02-17 10:29:32 -0700 |
commit | c0c44ae8a36121dc13f7984cf8b3347c21f43f51 (patch) | |
tree | 489bc30b7987a1dcf31ca2e8ba96a370e72e4a86 /pkg/api/server/handler_api.go | |
parent | 640b11f0028057ca2090d61c4e460c1afadb226c (diff) | |
download | podman-c0c44ae8a36121dc13f7984cf8b3347c21f43f51.tar.gz podman-c0c44ae8a36121dc13f7984cf8b3347c21f43f51.tar.bz2 podman-c0c44ae8a36121dc13f7984cf8b3347c21f43f51.zip |
Fix handler and systemd activation errors
On panic from handler: log warning and stack trace, report
InternalServerError to client
When using `podman system service` make determining the listening endpoint deterministic.
// When determining _*THE*_ listening endpoint --
// 1) User input wins always
// 2) systemd socket activation
// 3) rootless honors XDG_RUNTIME_DIR
// 4) if varlink -- adapter.DefaultVarlinkAddress
// 5) lastly adapter.DefaultAPIAddress
Fixes #5150
Fixes #5151
Signed-off-by: Jhon Honce <jhonce@redhat.com>
Diffstat (limited to 'pkg/api/server/handler_api.go')
-rw-r--r-- | pkg/api/server/handler_api.go | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go index 4b93998ee..30a1680c9 100644 --- a/pkg/api/server/handler_api.go +++ b/pkg/api/server/handler_api.go @@ -2,32 +2,52 @@ package server import ( "context" + "fmt" "net/http" + "runtime" + "github.com/containers/libpod/pkg/api/handlers/utils" log "github.com/sirupsen/logrus" ) // APIHandler is a wrapper to enhance HandlerFunc's and remove redundant code -func APIHandler(ctx context.Context, h http.HandlerFunc) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log.Debugf("APIHandler -- Method: %s URL: %s", r.Method, r.URL.String()) - if err := r.ParseForm(); err != nil { - log.Infof("Failed Request: unable to parse form: %q", err) - } +func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // http.Server hides panics, we want to see them and fix the cause. + defer func() { + err := recover() + if err != nil { + buf := make([]byte, 1<<20) + n := runtime.Stack(buf, true) + log.Warnf("Recovering from podman handler panic: %v, %s", err, buf[:n]) + // Try to inform client things went south... won't work if handler already started writing response body + utils.InternalServerError(w, fmt.Errorf("%v", err)) + } + }() + + // Wrapper to hide some boiler plate + fn := func(w http.ResponseWriter, r *http.Request) { + // Connection counting, ugh. Needed to support the sliding window for idle checking. + s.ConnectionCh <- EnterHandler + defer func() { s.ConnectionCh <- ExitHandler }() + + log.Debugf("APIHandler -- Method: %s URL: %s (conn %d/%d)", + r.Method, r.URL.String(), s.ActiveConnections, s.TotalConnections) - // TODO: Use ConnContext when ported to go 1.13 - c := context.WithValue(r.Context(), "decoder", ctx.Value("decoder")) - c = context.WithValue(c, "runtime", ctx.Value("runtime")) - c = context.WithValue(c, "shutdownFunc", ctx.Value("shutdownFunc")) - r = r.WithContext(c) + if err := r.ParseForm(); err != nil { + log.Infof("Failed Request: unable to parse form: %q", err) + } - h(w, r) + // TODO: Use r.ConnContext when ported to go 1.13 + c := context.WithValue(r.Context(), "decoder", s.Decoder) + c = context.WithValue(c, "runtime", s.Runtime) + c = context.WithValue(c, "shutdownFunc", s.Shutdown) + r = r.WithContext(c) - shutdownFunc := r.Context().Value("shutdownFunc").(func() error) - if err := shutdownFunc(); err != nil { - log.Errorf("Failed to shutdown Server in APIHandler(): %s", err.Error()) + h(w, r) } - }) + fn(w, r) + } } // VersionedPath prepends the version parsing code |