Add dumpStacks support for containerd on Windows

Resolves: #1763

Signed-off-by: Justin Terry (VM) <juterry@microsoft.com>
This commit is contained in:
Justin Terry (VM) 2018-11-27 15:36:23 -08:00
parent dcb82064d3
commit b4a642f6a5
3 changed files with 50 additions and 18 deletions

View File

@ -24,6 +24,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"runtime"
"time" "time"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
@ -232,3 +233,18 @@ func setLevel(context *cli.Context, config *srvconfig.Config) error {
} }
return nil 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 ( import (
"context" "context"
"os" "os"
"runtime"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/services/server" "github.com/containerd/containerd/services/server"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -66,18 +64,3 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
}() }()
return done 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 ( import (
"context" "context"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"unsafe"
winio "github.com/Microsoft/go-winio"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/services/server" "github.com/containerd/containerd/services/server"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@ -54,5 +57,35 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
} }
} }
}() }()
setupDumpStacks()
return done 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()
}
}()
}