aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-04-29 13:58:32 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-04-29 13:58:32 +0200
commit4b069590d130bce6793265d84bee67244e715be1 (patch)
tree0e4593fba8248a38c0d0602224be1f5e079a6b22 /service
parentservice: improve state transitions (diff)
downloadwireguard-windows-4b069590d130bce6793265d84bee67244e715be1.tar.xz
wireguard-windows-4b069590d130bce6793265d84bee67244e715be1.zip
service: tunnel: print stack and quit after 30 seconds of shutdown deadlock
Diffstat (limited to 'service')
-rw-r--r--service/service_tunnel.go45
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")
}()