From f784f33c2d2670cb73bc5c1fcbf1e2c01901cc94 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 Oct 2019 09:25:31 +0100 Subject: [PATCH 1/5] Backport fix for #581 from #583 --- src/multicast/multicast.go | 47 +++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/multicast/multicast.go b/src/multicast/multicast.go index 7044eaa2..ed8efafd 100644 --- a/src/multicast/multicast.go +++ b/src/multicast/multicast.go @@ -55,6 +55,21 @@ func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log // listen for multicast beacons from other hosts and will advertise multicast // beacons out to the network. func (m *Multicast) Start() error { + var err error + phony.Block(m, func() { + err = m._start() + }) + return err +} + +func (m *Multicast) _start() error { + if m.isOpen { + return fmt.Errorf("multicast module is already started") + } + if len(m.config.GetCurrent().MulticastInterfaces) == 0 { + return fmt.Errorf("no MulticastInterfaces configured") + } + m.log.Infoln("Starting multicast module") addr, err := net.ResolveUDPAddr("udp", m.groupAddr) if err != nil { return err @@ -80,8 +95,22 @@ func (m *Multicast) Start() error { return nil } -// Stop is not implemented for multicast yet. -func (m *Multicast) Stop() error { +// IsStarted returns true if the module has been started. +func (m *Multicast) IsStarted() bool { + var isOpen bool + phony.Block(m, func() { + isOpen = m.isOpen + }) + return isOpen +} + +// Stop stops the multicast module. +func (m *Multicast) Stop() { + m.Act(m, m._stop) +} + +func (m *Multicast) _stop() { + m.log.Infoln("Stopping multicast module") m.isOpen = false if m.announcer != nil { m.announcer.Stop() @@ -90,15 +119,27 @@ func (m *Multicast) Stop() error { m.platformhandler.Stop() } m.sock.Close() - return nil } // UpdateConfig updates the multicast module with the provided config.NodeConfig // and then signals the various module goroutines to reconfigure themselves if // needed. func (m *Multicast) UpdateConfig(config *config.NodeConfig) { + m.Act(m, func() { m._updateConfig(config) }) +} + +func (m *Multicast) _updateConfig(config *config.NodeConfig) { m.log.Debugln("Reloading multicast configuration...") + if m.IsStarted() { + if len(config.MulticastInterfaces) == 0 || config.LinkLocalTCPPort != m.listenPort { + m.Stop() + } + } m.config.Replace(*config) + m.listenPort = config.LinkLocalTCPPort + if !m.IsStarted() && len(config.MulticastInterfaces) > 0 { + m.Start() + } } // GetInterfaces returns the currently known/enabled multicast interfaces. It is From 5ca81f916ef1952e58d8699976eb9cb01a15cde8 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 Oct 2019 09:54:57 +0100 Subject: [PATCH 2/5] Fix deadlocks --- src/multicast/multicast.go | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/multicast/multicast.go b/src/multicast/multicast.go index ed8efafd..82d47ed0 100644 --- a/src/multicast/multicast.go +++ b/src/multicast/multicast.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "regexp" + "sync/atomic" "time" "github.com/Arceliar/phony" @@ -28,7 +29,7 @@ type Multicast struct { groupAddr string listeners map[string]*listenerInfo listenPort uint16 - isOpen bool + isOpen atomic.Value // bool announcer *time.Timer platformhandler *time.Timer } @@ -48,6 +49,7 @@ func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log current := m.config.GetCurrent() m.listenPort = current.LinkLocalTCPPort m.groupAddr = "[ff02::114]:9001" + m.isOpen.Store(false) return nil } @@ -59,15 +61,16 @@ func (m *Multicast) Start() error { phony.Block(m, func() { err = m._start() }) + m.log.Debugln("Started multicast module") return err } func (m *Multicast) _start() error { - if m.isOpen { + if m.IsStarted() { return fmt.Errorf("multicast module is already started") } if len(m.config.GetCurrent().MulticastInterfaces) == 0 { - return fmt.Errorf("no MulticastInterfaces configured") + return nil } m.log.Infoln("Starting multicast module") addr, err := net.ResolveUDPAddr("udp", m.groupAddr) @@ -87,7 +90,7 @@ func (m *Multicast) _start() error { // Windows can't set this flag, so we need to handle it in other ways } - m.isOpen = true + m.isOpen.Store(true) go m.listen() m.Act(m, m.multicastStarted) m.Act(m, m.announce) @@ -97,21 +100,25 @@ func (m *Multicast) _start() error { // IsStarted returns true if the module has been started. func (m *Multicast) IsStarted() bool { - var isOpen bool - phony.Block(m, func() { - isOpen = m.isOpen - }) - return isOpen + if m.isOpen.Load() == nil { + return false + } + return m.isOpen.Load().(bool) } // Stop stops the multicast module. -func (m *Multicast) Stop() { - m.Act(m, m._stop) +func (m *Multicast) Stop() error { + var err error + phony.Block(m, func() { + err = m._stop() + }) + m.log.Debugln("Stopped multicast module") + return nil } -func (m *Multicast) _stop() { +func (m *Multicast) _stop() error { m.log.Infoln("Stopping multicast module") - m.isOpen = false + m.isOpen.Store(false) if m.announcer != nil { m.announcer.Stop() } @@ -119,6 +126,7 @@ func (m *Multicast) _stop() { m.platformhandler.Stop() } m.sock.Close() + return nil } // UpdateConfig updates the multicast module with the provided config.NodeConfig @@ -129,17 +137,22 @@ func (m *Multicast) UpdateConfig(config *config.NodeConfig) { } func (m *Multicast) _updateConfig(config *config.NodeConfig) { - m.log.Debugln("Reloading multicast configuration...") + m.log.Infoln("Reloading multicast configuration...") if m.IsStarted() { if len(config.MulticastInterfaces) == 0 || config.LinkLocalTCPPort != m.listenPort { - m.Stop() + if err := m._stop(); err != nil { + m.log.Errorln("Error stopping multicast module:", err) + } } } m.config.Replace(*config) m.listenPort = config.LinkLocalTCPPort if !m.IsStarted() && len(config.MulticastInterfaces) > 0 { - m.Start() + if err := m._start(); err != nil { + m.log.Errorln("Error starting multicast module:", err) + } } + m.log.Debugln("Reloaded multicast configuration successfully") } // GetInterfaces returns the currently known/enabled multicast interfaces. It is @@ -312,7 +325,7 @@ func (m *Multicast) listen() { for { nBytes, rcm, fromAddr, err := m.sock.ReadFrom(bs) if err != nil { - if !m.isOpen { + if !m.IsStarted() { return } panic(err) From 51fe1940c593c2a97ecdf4118f0ffa452cc9cfc9 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 Oct 2019 10:13:59 +0100 Subject: [PATCH 3/5] Try go 1.13 to see if this fixes failing builds --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 146d5e53..33290840 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ version: 2.1 jobs: build-linux: docker: - - image: circleci/golang:1.13.3 + - image: circleci/golang:1.13 steps: - checkout From ee644c47e8be8d2fa41ddb614d48972a8044cbad Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 Oct 2019 10:16:52 +0100 Subject: [PATCH 4/5] Update go.mod/go.sum, go back to 1.13.3 circleci image again --- .circleci/config.yml | 2 +- go.mod | 17 +++++++---------- go.sum | 29 ++++++++++++----------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 33290840..146d5e53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ version: 2.1 jobs: build-linux: docker: - - image: circleci/golang:1.13 + - image: circleci/golang:1.13.3 steps: - checkout diff --git a/go.mod b/go.mod index d1a3587f..6d27e6ed 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,18 @@ module github.com/yggdrasil-network/yggdrasil-go +go 1.13 + require ( - github.com/Arceliar/phony v0.0.0-20191005181740-21679e75e3f0 + github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0 github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 github.com/hashicorp/go-syslog v1.0.0 - github.com/hjson/hjson-go v3.0.1-0.20190209023717-9147687966d9+incompatible + github.com/hjson/hjson-go v3.0.0+incompatible github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0 github.com/mitchellh/mapstructure v1.1.2 github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 - github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b // indirect - github.com/vishvananda/netlink v1.0.0 - github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f // indirect github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 - golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 - golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/net v0.0.0-20191021144547-ec77196f6094 + golang.org/x/sys v0.0.0-20191024073052-e66fe6eb8e0c golang.org/x/text v0.3.2 ) - -go 1.13 diff --git a/go.sum b/go.sum index bca7c231..61fc7242 100644 --- a/go.sum +++ b/go.sum @@ -1,35 +1,30 @@ -github.com/Arceliar/phony v0.0.0-20191005181740-21679e75e3f0 h1:IOFsvAMFkgnKfSQHxXTeqb1+ODFeR5px1HCHU86KF30= -github.com/Arceliar/phony v0.0.0-20191005181740-21679e75e3f0/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI= +github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0 h1:p3puK8Sl2xK+2FnnIvY/C0N1aqJo2kbEsdAzU+Tnv48= +github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI= github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 h1:WD8iJ37bRNwvETMfVTusVSAi0WdXTpfNVGY2aHycNKY= github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U= github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hjson/hjson-go v3.0.1-0.20190209023717-9147687966d9+incompatible h1:bLQ2Ve+eW65id3b8xEMQiAwJT4qGZeywAEMLvXjznvw= -github.com/hjson/hjson-go v3.0.1-0.20190209023717-9147687966d9+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= +github.com/hjson/hjson-go v3.0.0+incompatible h1:mc8olpIxqF8mrEx6ePJOD6wCCOkX7+JcrKgINcJES10= +github.com/hjson/hjson-go v3.0.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0 h1:YnZmFjg0Nvk8851WTVWlqMC1ecJH07Ctz+Ezxx4u54g= github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0/go.mod h1:rUi0/YffDo1oXBOGn1KRq7Fr07LX48XEBecQnmwjsAo= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 h1:1zN6ImoqhSJhN8hGXFaJlSC8msLmIbX8bFqOfWLKw0w= github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091/go.mod h1:N20Z5Y8oye9a7HmytmZ+tr8Q2vlP0tAHP13kTHzwvQY= -github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c= -github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= -github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= -github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I= -github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 h1:YY9Pg2BEp0jeUVU60svTOaDr+fs1ySC9RbdC1Qc6wOw= github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8/go.mod h1:R0SBCsugm+Sf1katgTb2t7GXMm+nRIv43tM4VDZbaOs= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8= +golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191024073052-e66fe6eb8e0c h1:usSYQsGq37L8RjJc5eznJ/AbwBxn3QFFEVkWNPAejLs= +golang.org/x/sys v0.0.0-20191024073052-e66fe6eb8e0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 0e7ed4c99771785b7817d5c5aa39f69be07124e2 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 Oct 2019 10:18:08 +0100 Subject: [PATCH 5/5] Actually really use 1.13.3 for all the builds this time --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 146d5e53..17cbfade 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -106,11 +106,11 @@ jobs: echo -e "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - run: - name: Install Go 1.12.7 + name: Install Go 1.13.3 command: | cd /tmp - curl -LO https://dl.google.com/go/go1.12.7.darwin-amd64.pkg - sudo installer -pkg /tmp/go1.12.7.darwin-amd64.pkg -target / + curl -LO https://dl.google.com/go/go1.13.3.darwin-amd64.pkg + sudo installer -pkg /tmp/go1.13.3.darwin-amd64.pkg -target / #- run: # name: Install Gomobile @@ -146,7 +146,7 @@ jobs: build-other: docker: - - image: circleci/golang:1.12.7 + - image: circleci/golang:1.13.3 steps: - checkout