Merge pull request #2837 from jterry75/containerd_dump_stacks

Add dumpStacks support for containerd on Windows
This commit is contained in:
Phil Estes 2018-11-28 11:38:58 +00:00 committed by GitHub
commit 1ce733a5ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 18 deletions

View File

@ -24,6 +24,7 @@ import (
"os"
"os/signal"
"path/filepath"
"runtime"
"time"
"github.com/containerd/containerd/log"
@ -232,3 +233,18 @@ func setLevel(context *cli.Context, config *srvconfig.Config) error {
}
return nil
}
func dumpStacks() {
var (
buf []byte
stackSize int
)
bufferLen := 16384
for stackSize == len(buf) {
buf = make([]byte, bufferLen)
stackSize = runtime.Stack(buf, true)
bufferLen *= 2
}
buf = buf[:stackSize]
logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}

View File

@ -21,11 +21,9 @@ package command
import (
"context"
"os"
"runtime"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/services/server"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@ -66,18 +64,3 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
}()
return done
}
func dumpStacks() {
var (
buf []byte
stackSize int
)
bufferLen := 16384
for stackSize == len(buf) {
buf = make([]byte, bufferLen)
stackSize = runtime.Stack(buf, true)
bufferLen *= 2
}
buf = buf[:stackSize]
logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}

View File

@ -18,12 +18,15 @@ package command
import (
"context"
"fmt"
"os"
"path/filepath"
"unsafe"
winio "github.com/Microsoft/go-winio"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/services/server"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
@ -54,5 +57,35 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
}
}
}()
setupDumpStacks()
return done
}
func setupDumpStacks() {
// Windows does not support signals like *nix systems. So instead of
// trapping on SIGUSR1 to dump stacks, we wait on a Win32 event to be
// signaled. ACL'd to builtin administrators and local system
event := "Global\\containerd-daemon-" + fmt.Sprint(os.Getpid())
ev, _ := windows.UTF16PtrFromString(event)
sd, err := winio.SddlToSecurityDescriptor("D:P(A;;GA;;;BA)(A;;GA;;;SY)")
if err != nil {
logrus.Errorf("failed to get security descriptor for debug stackdump event %s: %s", event, err.Error())
return
}
var sa windows.SecurityAttributes
sa.Length = uint32(unsafe.Sizeof(sa))
sa.InheritHandle = 1
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0]))
h, err := windows.CreateEvent(&sa, 0, 0, ev)
if h == 0 || err != nil {
logrus.Errorf("failed to create debug stackdump event %s: %s", event, err.Error())
return
}
go func() {
logrus.Debugf("Stackdump - waiting signal at %s", event)
for {
windows.WaitForSingleObject(h, windows.INFINITE)
dumpStacks()
}
}()
}