mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add command-line parameter to trigger panic on signal
This is to troubleshoot problems with a hung process that is not responding to 'runsc debug --stack' command. PiperOrigin-RevId: 210483513 Change-Id: I4377b210b4e51bc8a281ad34fd94f3df13d9187d
This commit is contained in:
committed by
Shentubot
parent
a4529c1b5b
commit
ae648bafda
@@ -103,7 +103,7 @@ func forwardSignals(k *kernel.Kernel, sigchans []chan os.Signal, start, stop cha
|
||||
// PrepareForwarding ensures that synchronous signals are forwarded to k and
|
||||
// returns a callback that starts signal delivery, which itself returns a
|
||||
// callback that stops signal forwarding.
|
||||
func PrepareForwarding(k *kernel.Kernel, enablePanicSignal bool) func() func() {
|
||||
func PrepareForwarding(k *kernel.Kernel, skipSignal syscall.Signal) func() func() {
|
||||
start := make(chan struct{})
|
||||
stop := make(chan struct{})
|
||||
|
||||
@@ -119,8 +119,7 @@ func PrepareForwarding(k *kernel.Kernel, enablePanicSignal bool) func() func() {
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
sigchans = append(sigchans, sigchan)
|
||||
|
||||
// SignalPanic is handled by Run.
|
||||
if enablePanicSignal && linux.Signal(sig) == kernel.SignalPanic {
|
||||
if syscall.Signal(sig) == skipSignal {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,12 @@ type Config struct {
|
||||
// TODO: Remove this when multiple container is fully supported.
|
||||
MultiContainer bool
|
||||
|
||||
// WatchdogAction sets what action the watchdog takes when triggered.
|
||||
WatchdogAction watchdog.Action
|
||||
|
||||
// PanicSignal register signal handling that panics. Usually set to
|
||||
// SIGUSR2(12) to troubleshoot hangs. -1 disables it.
|
||||
PanicSignal int
|
||||
}
|
||||
|
||||
// ToFlags returns a slice of flags that correspond to the given Config.
|
||||
@@ -225,5 +230,6 @@ func (c *Config) ToFlags() []string {
|
||||
"--strace-syscalls=" + strings.Join(c.StraceSyscalls, ","),
|
||||
"--strace-log-size=" + strconv.Itoa(int(c.StraceLogSize)),
|
||||
"--watchdog-action=" + c.WatchdogAction.String(),
|
||||
"--panic-signal=" + strconv.Itoa(c.PanicSignal),
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -229,7 +230,18 @@ func New(spec *specs.Spec, conf *Config, controllerFD int, ioFDs []int, console
|
||||
return nil, fmt.Errorf("failed to ignore child stop signals: %v", err)
|
||||
}
|
||||
// Ensure that signals received are forwarded to the emulated kernel.
|
||||
stopSignalForwarding := sighandling.PrepareForwarding(k, false)()
|
||||
ps := syscall.Signal(conf.PanicSignal)
|
||||
stopSignalForwarding := sighandling.PrepareForwarding(k, ps)()
|
||||
if conf.PanicSignal != -1 {
|
||||
// Panics if the sentry receives 'conf.PanicSignal'.
|
||||
panicChan := make(chan os.Signal, 1)
|
||||
signal.Notify(panicChan, ps)
|
||||
go func() { // S/R-SAFE: causes sentry panic.
|
||||
<-panicChan
|
||||
panic("Signal-induced panic")
|
||||
}()
|
||||
log.Infof("Panic signal set to %v(%d)", ps, conf.PanicSignal)
|
||||
}
|
||||
|
||||
procArgs, err := newProcess(spec, creds, utsns, ipcns, k)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"context"
|
||||
"flag"
|
||||
"github.com/google/subcommands"
|
||||
@@ -27,6 +29,7 @@ import (
|
||||
type Debug struct {
|
||||
pid int
|
||||
stacks bool
|
||||
signal int
|
||||
}
|
||||
|
||||
// Name implements subcommands.Command.
|
||||
@@ -48,6 +51,7 @@ func (*Debug) Usage() string {
|
||||
func (d *Debug) SetFlags(f *flag.FlagSet) {
|
||||
f.IntVar(&d.pid, "pid", 0, "sandbox process ID. Container ID is not necessary if this is set")
|
||||
f.BoolVar(&d.stacks, "stacks", false, "if true, dumps all sandbox stacks to the log")
|
||||
f.IntVar(&d.signal, "signal", -1, "sends signal to the sandbox")
|
||||
}
|
||||
|
||||
// Execute implements subcommands.Command.Execute.
|
||||
@@ -96,6 +100,12 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
|
||||
Fatalf("sandbox %q is not running", c.Sandbox.ID)
|
||||
}
|
||||
|
||||
if d.signal > 0 {
|
||||
log.Infof("Sending signal %d to process: %d", d.signal, c.Sandbox.Pid)
|
||||
if err := syscall.Kill(c.Sandbox.Pid, syscall.Signal(d.signal)); err != nil {
|
||||
Fatalf("failed to send signal %d to processs %d", d.signal, c.Sandbox.Pid)
|
||||
}
|
||||
}
|
||||
if d.stacks {
|
||||
log.Infof("Retrieving sandbox stacks")
|
||||
stacks, err := c.Sandbox.Stacks()
|
||||
|
||||
@@ -61,6 +61,7 @@ var (
|
||||
overlay = flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.")
|
||||
multiContainer = flag.Bool("multi-container", false, "enable *experimental* multi-container support.")
|
||||
watchdogAction = flag.String("watchdog-action", "log", "sets what action the watchdog takes when triggered: log (default), panic.")
|
||||
panicSignal = flag.Int("panic-signal", -1, "register signal handling that panics. Usually set to SIGUSR2(12) to troubleshoot hangs. -1 disables it.")
|
||||
)
|
||||
|
||||
var gitRevision = ""
|
||||
@@ -139,6 +140,7 @@ func main() {
|
||||
StraceLogSize: *straceLogSize,
|
||||
MultiContainer: *multiContainer,
|
||||
WatchdogAction: wa,
|
||||
PanicSignal: *panicSignal,
|
||||
}
|
||||
if len(*straceSyscalls) != 0 {
|
||||
conf.StraceSyscalls = strings.Split(*straceSyscalls, ",")
|
||||
|
||||
Reference in New Issue
Block a user