Skip to content

Commit

Permalink
Merge pull request containers#11869 from jwhonce/wip/pprof
Browse files Browse the repository at this point in the history
Enable /debug/pprof API service endpoints
  • Loading branch information
openshift-merge-robot authored Oct 10, 2021
2 parents c47f714 + 8d3aec9 commit 60c711f
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 114 deletions.
43 changes: 24 additions & 19 deletions cmd/podman/system/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ Enable a listening service for API access to Podman commands.
Long: srvDescription,
RunE: service,
ValidArgsFunction: common.AutocompleteDefaultOneArg,
Example: `podman system service --time=0 unix:///tmp/podman.sock`,
Example: `podman system service --time=0 unix:///tmp/podman.sock
podman system service --time=0 tcp://localhost:8888`,
}

srvArgs = struct {
Timeout int64
CorsHeaders string
PProfAddr string
Timeout uint
}{}
)

Expand All @@ -51,15 +53,20 @@ func init() {
})

flags := srvCmd.Flags()

cfg := registry.PodmanConfig()

timeFlagName := "time"
flags.Int64VarP(&srvArgs.Timeout, timeFlagName, "t", int64(cfg.Engine.ServiceTimeout), "Time until the service session expires in seconds. Use 0 to disable the timeout")
flags.UintVarP(&srvArgs.Timeout, timeFlagName, "t", cfg.Engine.ServiceTimeout,
"Time until the service session expires in seconds. Use 0 to disable the timeout")
_ = srvCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone)
flags.SetNormalizeFunc(aliasTimeoutFlag)

flags.StringVarP(&srvArgs.CorsHeaders, "cors", "", "", "Set CORS Headers")
_ = srvCmd.RegisterFlagCompletionFunc("cors", completion.AutocompleteNone)

flags.SetNormalizeFunc(aliasTimeoutFlag)
flags.StringVarP(&srvArgs.PProfAddr, "pprof-address", "", "",
"Binding network address for pprof profile endpoints, default: do not expose endpoints")
flags.MarkHidden("pprof-address")
}

func aliasTimeoutFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName {
Expand All @@ -74,7 +81,7 @@ func service(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
logrus.Infof("Using API endpoint: '%s'", apiURI)

// Clean up any old existing unix domain socket
if len(apiURI) > 0 {
uri, err := url.Parse(apiURI)
Expand All @@ -92,33 +99,31 @@ func service(cmd *cobra.Command, args []string) error {
}
}

opts := entities.ServiceOptions{
URI: apiURI,
Command: cmd,
return restService(cmd.Flags(), registry.PodmanConfig(), entities.ServiceOptions{
CorsHeaders: srvArgs.CorsHeaders,
}

opts.Timeout = time.Duration(srvArgs.Timeout) * time.Second
return restService(opts, cmd.Flags(), registry.PodmanConfig())
PProfAddr: srvArgs.PProfAddr,
Timeout: time.Duration(srvArgs.Timeout) * time.Second,
URI: apiURI,
})
}

func resolveAPIURI(_url []string) (string, error) {
func resolveAPIURI(uri []string) (string, error) {
// When determining _*THE*_ listening endpoint --
// 1) User input wins always
// 2) systemd socket activation
// 3) rootless honors XDG_RUNTIME_DIR
// 4) lastly adapter.DefaultAPIAddress

if len(_url) == 0 {
if len(uri) == 0 {
if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
logrus.Debugf("PODMAN_SOCKET='%s' used to determine API endpoint", v)
_url = []string{v}
logrus.Debugf("PODMAN_SOCKET=%q used to determine API endpoint", v)
uri = []string{v}
}
}

switch {
case len(_url) > 0 && _url[0] != "":
return _url[0], nil
case len(uri) > 0 && uri[0] != "":
return uri[0], nil
case systemd.SocketActivated():
logrus.Info("Using systemd socket activation to determine API endpoint")
return "", nil
Expand Down
61 changes: 37 additions & 24 deletions cmd/podman/system/service_abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ package system
import (
"context"
"net"
"net/url"
"os"
"path/filepath"
"strings"

api "github.com/containers/podman/v3/pkg/api/server"
"github.com/containers/podman/v3/pkg/domain/entities"
Expand All @@ -20,41 +20,54 @@ import (
"golang.org/x/sys/unix"
)

func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entities.PodmanConfig) error {
func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities.ServiceOptions) error {
var (
listener *net.Listener
err error
)

if opts.URI != "" {
fields := strings.Split(opts.URI, ":")
if len(fields) == 1 {
uri, err := url.Parse(opts.URI)
if err != nil {
return errors.Errorf("%s is an invalid socket destination", opts.URI)
}
path := opts.URI
if fields[0] == "unix" {
if path, err = filepath.Abs(fields[1]); err != nil {
return err
}
}
util.SetSocketPath(path)
if os.Getenv("LISTEN_FDS") != "" {
// If it is activated by systemd, use the first LISTEN_FD (3)
// instead of opening the socket file.
f := os.NewFile(uintptr(3), "podman.sock")
l, err := net.FileListener(f)

switch uri.Scheme {
case "unix":
path, err := filepath.Abs(uri.Path)
if err != nil {
return err
}
listener = &l
} else {
network := fields[0]
address := strings.Join(fields[1:], ":")
l, err := net.Listen(network, address)
util.SetSocketPath(path)
if os.Getenv("LISTEN_FDS") != "" {
// If it is activated by systemd, use the first LISTEN_FD (3)
// instead of opening the socket file.
f := os.NewFile(uintptr(3), "podman.sock")
l, err := net.FileListener(f)
if err != nil {
return err
}
listener = &l
} else {
l, err := net.Listen(uri.Scheme, path)
if err != nil {
return errors.Wrapf(err, "unable to create socket")
}
listener = &l
}
case "tcp":
host := uri.Host
if host == "" {
// For backward compatibility, support "tcp:<host>:<port>" and "tcp://<host>:<port>"
host = uri.Opaque
}
l, err := net.Listen(uri.Scheme, host)
if err != nil {
return errors.Wrapf(err, "unable to create socket")
return errors.Wrapf(err, "unable to create socket %v", host)
}
listener = &l
default:
logrus.Debugf("Attempting API Service endpoint scheme %q", uri.Scheme)
}
}

Expand All @@ -75,12 +88,12 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti
servicereaper.Start()

infra.StartWatcher(rt)
server, err := api.NewServerWithSettings(rt, listener, api.Options{Timeout: opts.Timeout, CorsHeaders: opts.CorsHeaders})
server, err := api.NewServerWithSettings(rt, listener, opts)
if err != nil {
return err
}
defer func() {
if err := server.Shutdown(); err != nil {
if err := server.Shutdown(false); err != nil {
logrus.Warnf("Error when stopping API service: %s", err)
}
}()
Expand Down
4 changes: 2 additions & 2 deletions libpod/shutdown/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ func Stop() error {
return nil
}

// Temporarily inhibit signals from shutting down Libpod.
// Inhibit temporarily inhibit signals from shutting down Libpod.
func Inhibit() {
shutdownInhibit.RLock()
}

// Stop inhibiting signals from shutting down Libpod.
// Uninhibit stop inhibiting signals from shutting down Libpod.
func Uninhibit() {
shutdownInhibit.RUnlock()
}
Expand Down
Loading

0 comments on commit 60c711f

Please sign in to comment.