diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-04-29 13:58:32 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-04-29 13:58:32 +0200 |
commit | 4b069590d130bce6793265d84bee67244e715be1 (patch) | |
tree | 0e4593fba8248a38c0d0602224be1f5e079a6b22 /service | |
parent | service: improve state transitions (diff) | |
download | wireguard-windows-4b069590d130bce6793265d84bee67244e715be1.tar.xz wireguard-windows-4b069590d130bce6793265d84bee67244e715be1.zip |
service: tunnel: print stack and quit after 30 seconds of shutdown deadlock
Diffstat (limited to '')
-rw-r--r-- | service/service_tunnel.go | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/service/service_tunnel.go b/service/service_tunnel.go index 12977d26..ba1b8ae0 100644 --- a/service/service_tunnel.go +++ b/service/service_tunnel.go @@ -7,6 +7,7 @@ package service import ( "bufio" + "bytes" "fmt" "golang.org/x/sys/windows/svc" "golang.zx2c4.com/winipcfg" @@ -17,8 +18,11 @@ import ( "golang.zx2c4.com/wireguard/windows/ringlogger" "log" "net" + "os" + "runtime" "runtime/debug" "strings" + "time" ) type tunnelService struct { @@ -38,14 +42,48 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, defer func() { svcSpecificEC, exitCode = determineErrorCode(err, serviceError) logErr := combineErrors(err, serviceError) - if logErr != nil { + logIt := func(a ...interface{}) { if logger != nil { - logger.Error.Print(logErr) + logger.Error.Print(a...) } else { - log.Print(logErr) + log.Print(a...) } } + if logErr != nil { + logIt(logErr) + } changes <- svc.Status{State: svc.StopPending} + + stopIt := make(chan bool, 1) + go func() { + t := time.NewTicker(time.Second * 30) + for { + select { + case <-t.C: + t.Stop() + buf := make([]byte, 1024) + for { + n := runtime.Stack(buf, true) + if n < len(buf) { + buf = buf[:n] + break + } + buf = make([]byte, 2*len(buf)) + } + lines := bytes.Split(buf, []byte{'\n'}) + logIt("Failed to shutdown after 30 seconds. Probably dead locked. Printing stack and killing.") + for _, line := range lines { + logIt(fmt.Sprintf("stack trace: %s", string(line))) + } + os.Exit(777) + return + case <-stopIt: + t.Stop() + return + } + } + }() + if routeChangeCallback != nil { routeChangeCallback.Unregister() } @@ -55,6 +93,7 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, if dev != nil { dev.Close() } + stopIt <- true log.Print("Shutting down") }() |