Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -568,8 +568,9 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo |
| 568 | 568 |
return nil, err |
| 569 | 569 |
} |
| 570 | 570 |
|
| 571 |
- // set up SIGUSR1 handler to dump Go routine stacks |
|
| 572 |
- setupSigusr1Trap() |
|
| 571 |
+ // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event |
|
| 572 |
+ // on Windows to dump Go routine stacks |
|
| 573 |
+ setupDumpStackTrap() |
|
| 573 | 574 |
|
| 574 | 575 |
// get the canonical path to the Docker root directory |
| 575 | 576 |
var realRoot string |
| 576 | 577 |
deleted file mode 100644 |
| ... | ... |
@@ -1,21 +0,0 @@ |
| 1 |
-// +build !windows |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "os" |
|
| 7 |
- "os/signal" |
|
| 8 |
- "syscall" |
|
| 9 |
- |
|
| 10 |
- psignal "github.com/docker/docker/pkg/signal" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-func setupSigusr1Trap() {
|
|
| 14 |
- c := make(chan os.Signal, 1) |
|
| 15 |
- signal.Notify(c, syscall.SIGUSR1) |
|
| 16 |
- go func() {
|
|
| 17 |
- for range c {
|
|
| 18 |
- psignal.DumpStacks() |
|
| 19 |
- } |
|
| 20 |
- }() |
|
| 21 |
-} |
| 22 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,21 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package daemon |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os" |
|
| 6 |
+ "os/signal" |
|
| 7 |
+ "syscall" |
|
| 8 |
+ |
|
| 9 |
+ psignal "github.com/docker/docker/pkg/signal" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func setupDumpStackTrap() {
|
|
| 13 |
+ c := make(chan os.Signal, 1) |
|
| 14 |
+ signal.Notify(c, syscall.SIGUSR1) |
|
| 15 |
+ go func() {
|
|
| 16 |
+ for range c {
|
|
| 17 |
+ psignal.DumpStacks() |
|
| 18 |
+ } |
|
| 19 |
+ }() |
|
| 20 |
+} |
| 8 | 8 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,30 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os" |
|
| 5 |
+ "syscall" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+ psignal "github.com/docker/docker/pkg/signal" |
|
| 9 |
+ "github.com/docker/docker/pkg/system" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func setupDumpStackTrap() {
|
|
| 13 |
+ // Windows does not support signals like *nix systems. So instead of |
|
| 14 |
+ // trapping on SIGUSR1 to dump stacks, we wait on a Win32 event to be |
|
| 15 |
+ // signalled. |
|
| 16 |
+ go func() {
|
|
| 17 |
+ sa := syscall.SecurityAttributes{
|
|
| 18 |
+ Length: 0, |
|
| 19 |
+ } |
|
| 20 |
+ ev := "Global\\docker-daemon-" + fmt.Sprint(os.Getpid()) |
|
| 21 |
+ if h, _ := system.CreateEvent(&sa, false, false, ev); h != 0 {
|
|
| 22 |
+ logrus.Debugf("Stackdump - waiting signal at %s", ev)
|
|
| 23 |
+ for {
|
|
| 24 |
+ syscall.WaitForSingleObject(h, syscall.INFINITE) |
|
| 25 |
+ psignal.DumpStacks() |
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ }() |
|
| 29 |
+} |
| 0 | 30 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,83 @@ |
| 0 |
+package system |
|
| 1 |
+ |
|
| 2 |
+// This file implements syscalls for Win32 events which are not implemented |
|
| 3 |
+// in golang. |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+const ( |
|
| 11 |
+ EVENT_ALL_ACCESS = 0x1F0003 |
|
| 12 |
+ EVENT_MODIFY_STATUS = 0x0002 |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+var ( |
|
| 16 |
+ procCreateEvent = modkernel32.NewProc("CreateEventW")
|
|
| 17 |
+ procOpenEvent = modkernel32.NewProc("OpenEventW")
|
|
| 18 |
+ procSetEvent = modkernel32.NewProc("SetEvent")
|
|
| 19 |
+ procResetEvent = modkernel32.NewProc("ResetEvent")
|
|
| 20 |
+ procPulseEvent = modkernel32.NewProc("PulseEvent")
|
|
| 21 |
+) |
|
| 22 |
+ |
|
| 23 |
+func CreateEvent(eventAttributes *syscall.SecurityAttributes, manualReset bool, initialState bool, name string) (handle syscall.Handle, err error) {
|
|
| 24 |
+ namep, _ := syscall.UTF16PtrFromString(name) |
|
| 25 |
+ var _p1 uint32 = 0 |
|
| 26 |
+ if manualReset {
|
|
| 27 |
+ _p1 = 1 |
|
| 28 |
+ } |
|
| 29 |
+ var _p2 uint32 = 0 |
|
| 30 |
+ if initialState {
|
|
| 31 |
+ _p2 = 1 |
|
| 32 |
+ } |
|
| 33 |
+ r0, _, e1 := procCreateEvent.Call(uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(namep))) |
|
| 34 |
+ use(unsafe.Pointer(namep)) |
|
| 35 |
+ handle = syscall.Handle(r0) |
|
| 36 |
+ if handle == syscall.InvalidHandle {
|
|
| 37 |
+ err = e1 |
|
| 38 |
+ } |
|
| 39 |
+ return |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func OpenEvent(desiredAccess uint32, inheritHandle bool, name string) (handle syscall.Handle, err error) {
|
|
| 43 |
+ namep, _ := syscall.UTF16PtrFromString(name) |
|
| 44 |
+ var _p1 uint32 = 0 |
|
| 45 |
+ if inheritHandle {
|
|
| 46 |
+ _p1 = 1 |
|
| 47 |
+ } |
|
| 48 |
+ r0, _, e1 := procOpenEvent.Call(uintptr(desiredAccess), uintptr(_p1), uintptr(unsafe.Pointer(namep))) |
|
| 49 |
+ use(unsafe.Pointer(namep)) |
|
| 50 |
+ handle = syscall.Handle(r0) |
|
| 51 |
+ if handle == syscall.InvalidHandle {
|
|
| 52 |
+ err = e1 |
|
| 53 |
+ } |
|
| 54 |
+ return |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 57 |
+func SetEvent(handle syscall.Handle) (err error) {
|
|
| 58 |
+ return setResetPulse(handle, procSetEvent) |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+func ResetEvent(handle syscall.Handle) (err error) {
|
|
| 62 |
+ return setResetPulse(handle, procResetEvent) |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func PulseEvent(handle syscall.Handle) (err error) {
|
|
| 66 |
+ return setResetPulse(handle, procPulseEvent) |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+func setResetPulse(handle syscall.Handle, proc *syscall.LazyProc) (err error) {
|
|
| 70 |
+ r0, _, _ := proc.Call(uintptr(handle)) |
|
| 71 |
+ if r0 != 0 {
|
|
| 72 |
+ err = syscall.Errno(r0) |
|
| 73 |
+ } |
|
| 74 |
+ return |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+var temp unsafe.Pointer |
|
| 78 |
+ |
|
| 79 |
+// use ensures a variable is kept alive without the GC freeing while still needed |
|
| 80 |
+func use(p unsafe.Pointer) {
|
|
| 81 |
+ temp = p |
|
| 82 |
+} |