aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-04-29 13:30:28 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-04-29 13:44:04 +0200
commitabb090fdb929d2cd372fe2adcc8113b993a306fc (patch)
tree86c554d239919013446eb101309f6488535766a3 /service
parentupdater: use /qb instead of /quiet (diff)
downloadwireguard-windows-abb090fdb929d2cd372fe2adcc8113b993a306fc.tar.xz
wireguard-windows-abb090fdb929d2cd372fe2adcc8113b993a306fc.zip
service: improve state transitions
Diffstat (limited to 'service')
-rw-r--r--service/install.go6
-rw-r--r--service/ipc_server.go27
-rw-r--r--service/service_tunnel.go11
3 files changed, 33 insertions, 11 deletions
diff --git a/service/install.go b/service/install.go
index 95c42b2f..e20658e9 100644
--- a/service/install.go
+++ b/service/install.go
@@ -129,17 +129,17 @@ func InstallTunnel(configPath string) error {
service, err := m.OpenService(serviceName)
if err == nil {
status, err := service.Query()
- if err != nil {
+ if err != nil && err != syscall.Errno(serviceMARKED_FOR_DELETE) {
service.Close()
return err
}
- if status.State != svc.Stopped {
+ if status.State != svc.Stopped && err != syscall.Errno(serviceMARKED_FOR_DELETE) {
service.Close()
return errors.New("Tunnel already installed and running")
}
err = service.Delete()
service.Close()
- if err != nil {
+ if err != nil && err != syscall.Errno(serviceMARKED_FOR_DELETE) {
return err
}
for {
diff --git a/service/ipc_server.go b/service/ipc_server.go
index 6d576846..4dd36b2d 100644
--- a/service/ipc_server.go
+++ b/service/ipc_server.go
@@ -8,10 +8,12 @@ package service
import (
"bytes"
"encoding/gob"
+ "fmt"
"github.com/Microsoft/go-winio"
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/windows/conf"
"io/ioutil"
+ "log"
"net/rpc"
"os"
"sync"
@@ -74,13 +76,32 @@ func (s *ManagerService) Start(tunnelName string, unused *uintptr) error {
// For now, enforce only one tunnel at a time. Later we'll remove this silly restriction.
trackedTunnelsLock.Lock()
tt := make([]string, 0, len(trackedTunnels))
- for t := range trackedTunnels {
+ var inTransition string
+ for t, state := range trackedTunnels {
tt = append(tt, t)
+ if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
+ inTransition = t
+ break
+ }
}
trackedTunnelsLock.Unlock()
- for _, t := range tt {
- s.Stop(t, unused)
+ if len(inTransition) != 0 {
+ return fmt.Errorf("Please allow the tunnel \"%s\" to finish activating", inTransition)
}
+ go func() {
+ for _, t := range tt {
+ s.Stop(t, unused)
+ }
+ for _, t := range tt {
+ var state TunnelState
+ var unused uintptr
+ if s.State(t, &state) == nil && (state == TunnelStarted || state == TunnelStarting) {
+ log.Printf("[%s] Trying again to stop zombie tunnel", t)
+ s.Stop(t, &unused)
+ time.Sleep(time.Millisecond * 100)
+ }
+ }
+ }()
// After that process is started -- it's somewhat asynchronous -- we install the new one.
c, err := conf.LoadFromName(tunnelName)
diff --git a/service/service_tunnel.go b/service/service_tunnel.go
index dd681a33..12977d26 100644
--- a/service/service_tunnel.go
+++ b/service/service_tunnel.go
@@ -82,6 +82,12 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
logger.Info.Println("Starting wireguard-go version", device.WireGuardGoVersion)
logger.Debug.Println("Debug log enabled")
+ uapiConf, err := conf.ToUAPI()
+ if err != nil {
+ serviceError = ErrorDNSLookup
+ return
+ }
+
wintun, err := tun.CreateTUN(conf.Name)
if err != nil {
serviceError = ErrorCreateWintun
@@ -115,11 +121,6 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}()
logger.Info.Println("UAPI listener started")
- uapiConf, err := conf.ToUAPI()
- if err != nil {
- serviceError = ErrorDNSLookup
- return
- }
ipcErr := dev.IpcSetOperation(bufio.NewReader(strings.NewReader(uapiConf)))
if ipcErr != nil {
err = ipcErr