summaryrefslogtreecommitdiffhomepage
path: root/runsc
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2020-08-05 11:28:15 -0700
committergVisor bot <gvisor-bot@google.com>2020-08-05 11:30:11 -0700
commit190b1e6bd4aae56eff3ff846efea38629361b3a9 (patch)
tree673703a8fc2de5ab1b273f05950efbcb9359e8a3 /runsc
parentd0127b23f26d546db0d525201f0ad3f43d5b8d24 (diff)
Stop profiling when the sentry exits
Also removes `--profile-goroutine` because it's equivalent to `debug --stacks`. PiperOrigin-RevId: 325061502
Diffstat (limited to 'runsc')
-rw-r--r--runsc/boot/controller.go51
-rw-r--r--runsc/boot/loader.go3
-rw-r--r--runsc/cmd/debug.go40
-rw-r--r--runsc/sandbox/sandbox.go20
4 files changed, 46 insertions, 68 deletions
diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go
index 3e5e4c22f..626a3816e 100644
--- a/runsc/boot/controller.go
+++ b/runsc/boot/controller.go
@@ -101,14 +101,13 @@ const (
// Profiling related commands (see pprof.go for more details).
const (
- StartCPUProfile = "Profile.StartCPUProfile"
- StopCPUProfile = "Profile.StopCPUProfile"
- HeapProfile = "Profile.HeapProfile"
- GoroutineProfile = "Profile.GoroutineProfile"
- BlockProfile = "Profile.BlockProfile"
- MutexProfile = "Profile.MutexProfile"
- StartTrace = "Profile.StartTrace"
- StopTrace = "Profile.StopTrace"
+ StartCPUProfile = "Profile.StartCPUProfile"
+ StopCPUProfile = "Profile.StopCPUProfile"
+ HeapProfile = "Profile.HeapProfile"
+ BlockProfile = "Profile.BlockProfile"
+ MutexProfile = "Profile.MutexProfile"
+ StartTrace = "Profile.StartTrace"
+ StopTrace = "Profile.StopTrace"
)
// Logging related commands (see logging.go for more details).
@@ -129,42 +128,52 @@ type controller struct {
// manager holds the containerManager methods.
manager *containerManager
+
+ // pprop holds the profile instance if enabled. It may be nil.
+ pprof *control.Profile
}
// newController creates a new controller. The caller must call
// controller.srv.StartServing() to start the controller.
func newController(fd int, l *Loader) (*controller, error) {
- srv, err := server.CreateFromFD(fd)
+ ctrl := &controller{}
+ var err error
+ ctrl.srv, err = server.CreateFromFD(fd)
if err != nil {
return nil, err
}
- manager := &containerManager{
+ ctrl.manager = &containerManager{
startChan: make(chan struct{}),
startResultChan: make(chan error),
l: l,
}
- srv.Register(manager)
+ ctrl.srv.Register(ctrl.manager)
if eps, ok := l.k.RootNetworkNamespace().Stack().(*netstack.Stack); ok {
net := &Network{
Stack: eps.Stack,
}
- srv.Register(net)
+ ctrl.srv.Register(net)
}
- srv.Register(&debug{})
- srv.Register(&control.Logging{})
+ ctrl.srv.Register(&debug{})
+ ctrl.srv.Register(&control.Logging{})
+
if l.root.conf.ProfileEnable {
- srv.Register(&control.Profile{
- Kernel: l.k,
- })
+ ctrl.pprof = &control.Profile{Kernel: l.k}
+ ctrl.srv.Register(ctrl.pprof)
}
- return &controller{
- srv: srv,
- manager: manager,
- }, nil
+ return ctrl, nil
+}
+
+func (c *controller) stop() {
+ if c.pprof != nil {
+ // These are noop if there is nothing being profiled.
+ _ = c.pprof.StopCPUProfile(nil, nil)
+ _ = c.pprof.StopTrace(nil, nil)
+ }
}
// containerManager manages sandbox containers.
diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go
index 92f0b16e1..533b9c5e7 100644
--- a/runsc/boot/loader.go
+++ b/runsc/boot/loader.go
@@ -1008,6 +1008,9 @@ func (l *Loader) WaitExit() kernel.ExitStatus {
// Wait for container.
l.k.WaitExited()
+ // Cleanup
+ l.ctrl.stop()
+
return l.k.GlobalInit().ExitStatus()
}
diff --git a/runsc/cmd/debug.go b/runsc/cmd/debug.go
index b5de2588b..742f8c344 100644
--- a/runsc/cmd/debug.go
+++ b/runsc/cmd/debug.go
@@ -32,20 +32,19 @@ import (
// Debug implements subcommands.Command for the "debug" command.
type Debug struct {
- pid int
- stacks bool
- signal int
- profileHeap string
- profileCPU string
- profileGoroutine string
- profileBlock string
- profileMutex string
- trace string
- strace string
- logLevel string
- logPackets string
- duration time.Duration
- ps bool
+ pid int
+ stacks bool
+ signal int
+ profileHeap string
+ profileCPU string
+ profileBlock string
+ profileMutex string
+ trace string
+ strace string
+ logLevel string
+ logPackets string
+ duration time.Duration
+ ps bool
}
// Name implements subcommands.Command.
@@ -69,7 +68,6 @@ func (d *Debug) SetFlags(f *flag.FlagSet) {
f.BoolVar(&d.stacks, "stacks", false, "if true, dumps all sandbox stacks to the log")
f.StringVar(&d.profileHeap, "profile-heap", "", "writes heap profile to the given file.")
f.StringVar(&d.profileCPU, "profile-cpu", "", "writes CPU profile to the given file.")
- f.StringVar(&d.profileGoroutine, "profile-goroutine", "", "writes goroutine profile to the given file.")
f.StringVar(&d.profileBlock, "profile-block", "", "writes block profile to the given file.")
f.StringVar(&d.profileMutex, "profile-mutex", "", "writes mutex profile to the given file.")
f.DurationVar(&d.duration, "duration", time.Second, "amount of time to wait for CPU and trace profiles")
@@ -153,18 +151,6 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
}
log.Infof("Heap profile written to %q", d.profileHeap)
}
- if d.profileGoroutine != "" {
- f, err := os.Create(d.profileGoroutine)
- if err != nil {
- return Errorf(err.Error())
- }
- defer f.Close()
-
- if err := c.Sandbox.GoroutineProfile(f); err != nil {
- return Errorf(err.Error())
- }
- log.Infof("Goroutine profile written to %q", d.profileGoroutine)
- }
if d.profileBlock != "" {
f, err := os.Create(d.profileBlock)
if err != nil {
diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go
index 2afcc27af..36bb0c9c9 100644
--- a/runsc/sandbox/sandbox.go
+++ b/runsc/sandbox/sandbox.go
@@ -1012,26 +1012,6 @@ func (s *Sandbox) StopCPUProfile() error {
return nil
}
-// GoroutineProfile writes a goroutine profile to the given file.
-func (s *Sandbox) GoroutineProfile(f *os.File) error {
- log.Debugf("Goroutine profile %q", s.ID)
- conn, err := s.sandboxConnect()
- if err != nil {
- return err
- }
- defer conn.Close()
-
- opts := control.ProfileOpts{
- FilePayload: urpc.FilePayload{
- Files: []*os.File{f},
- },
- }
- if err := conn.Call(boot.GoroutineProfile, &opts, nil); err != nil {
- return fmt.Errorf("getting sandbox %q goroutine profile: %v", s.ID, err)
- }
- return nil
-}
-
// BlockProfile writes a block profile to the given file.
func (s *Sandbox) BlockProfile(f *os.File) error {
log.Debugf("Block profile %q", s.ID)