f4b08c7f |
package daemon
import (
"fmt"
"os" |
192e6d99 |
"unsafe" |
f4b08c7f |
|
192e6d99 |
winio "github.com/Microsoft/go-winio" |
59d88785 |
"github.com/docker/docker/pkg/signal" |
1009e6a4 |
"github.com/sirupsen/logrus" |
069fdc8a |
"golang.org/x/sys/windows" |
f4b08c7f |
)
|
4c62b126 |
func (d *Daemon) setupDumpStackTrap(root string) { |
f4b08c7f |
// 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 |
192e6d99 |
// signaled. ACL'd to builtin administrators and local system |
7d0dea10 |
event := "Global\\docker-daemon-" + fmt.Sprint(os.Getpid())
ev, _ := windows.UTF16PtrFromString(event) |
192e6d99 |
sd, err := winio.SddlToSecurityDescriptor("D:P(A;;GA;;;BA)(A;;GA;;;SY)")
if err != nil { |
7d0dea10 |
logrus.Errorf("failed to get security descriptor for debug stackdump event %s: %s", event, err.Error()) |
192e6d99 |
return
} |
069fdc8a |
var sa windows.SecurityAttributes |
192e6d99 |
sa.Length = uint32(unsafe.Sizeof(sa))
sa.InheritHandle = 1
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) |
e942513a |
h, err := windows.CreateEvent(&sa, 0, 0, ev) |
192e6d99 |
if h == 0 || err != nil { |
7d0dea10 |
logrus.Errorf("failed to create debug stackdump event %s: %s", event, err.Error()) |
192e6d99 |
return
} |
f4b08c7f |
go func() { |
7d0dea10 |
logrus.Debugf("Stackdump - waiting signal at %s", event) |
192e6d99 |
for { |
069fdc8a |
windows.WaitForSingleObject(h, windows.INFINITE) |
e5d36586 |
path, err := signal.DumpStacks(root)
if err != nil {
logrus.WithError(err).Error("failed to write goroutines dump") |
4c62b126 |
} else {
logrus.Infof("goroutine stacks written to %s", path)
} |
f4b08c7f |
}
}()
} |