Don't panic on clean shutdown

This commit is contained in:
Jakob Borg 2015-10-20 15:14:05 +02:00
parent b2da0120d6
commit aa42aafe33
2 changed files with 43 additions and 23 deletions

View File

@ -11,6 +11,7 @@ import (
"net" "net"
"time" "time"
"github.com/syncthing/syncthing/lib/sync"
"github.com/thejerf/suture" "github.com/thejerf/suture"
) )
@ -44,11 +45,13 @@ func NewBroadcast(port int) *Broadcast {
b.br = &broadcastReader{ b.br = &broadcastReader{
port: port, port: port,
outbox: b.outbox, outbox: b.outbox,
connMut: sync.NewMutex(),
} }
b.Add(b.br) b.Add(b.br)
b.bw = &broadcastWriter{ b.bw = &broadcastWriter{
port: port, port: port,
inbox: b.inbox, inbox: b.inbox,
connMut: sync.NewMutex(),
} }
b.Add(b.bw) b.Add(b.bw)
@ -75,6 +78,7 @@ type broadcastWriter struct {
port int port int
inbox chan []byte inbox chan []byte
conn *net.UDPConn conn *net.UDPConn
connMut sync.Mutex
errorHolder errorHolder
} }
@ -82,14 +86,17 @@ func (w *broadcastWriter) Serve() {
l.Debugln(w, "starting") l.Debugln(w, "starting")
defer l.Debugln(w, "stopping") defer l.Debugln(w, "stopping")
var err error conn, err := net.ListenUDP("udp4", nil)
w.conn, err = net.ListenUDP("udp4", nil)
if err != nil { if err != nil {
l.Debugln(err) l.Debugln(err)
w.setError(err) w.setError(err)
return return
} }
defer w.conn.Close() defer conn.Close()
w.connMut.Lock()
w.conn = conn
w.connMut.Unlock()
for bs := range w.inbox { for bs := range w.inbox {
addrs, err := net.InterfaceAddrs() addrs, err := net.InterfaceAddrs()
@ -118,9 +125,9 @@ func (w *broadcastWriter) Serve() {
for _, ip := range dsts { for _, ip := range dsts {
dst := &net.UDPAddr{IP: ip, Port: w.port} dst := &net.UDPAddr{IP: ip, Port: w.port}
w.conn.SetWriteDeadline(time.Now().Add(time.Second)) conn.SetWriteDeadline(time.Now().Add(time.Second))
_, err := w.conn.WriteTo(bs, dst) _, err := conn.WriteTo(bs, dst)
w.conn.SetWriteDeadline(time.Time{}) conn.SetWriteDeadline(time.Time{})
if err, ok := err.(net.Error); ok && err.Timeout() { if err, ok := err.(net.Error); ok && err.Timeout() {
// Write timeouts should not happen. We treat it as a fatal // Write timeouts should not happen. We treat it as a fatal
@ -154,8 +161,12 @@ func (w *broadcastWriter) Serve() {
} }
func (w *broadcastWriter) Stop() { func (w *broadcastWriter) Stop() {
w.connMut.Lock()
if w.conn != nil {
w.conn.Close() w.conn.Close()
} }
w.connMut.Unlock()
}
func (w *broadcastWriter) String() string { func (w *broadcastWriter) String() string {
return fmt.Sprintf("broadcastWriter@%p", w) return fmt.Sprintf("broadcastWriter@%p", w)
@ -165,6 +176,7 @@ type broadcastReader struct {
port int port int
outbox chan recv outbox chan recv
conn *net.UDPConn conn *net.UDPConn
connMut sync.Mutex
errorHolder errorHolder
} }
@ -172,18 +184,21 @@ func (r *broadcastReader) Serve() {
l.Debugln(r, "starting") l.Debugln(r, "starting")
defer l.Debugln(r, "stopping") defer l.Debugln(r, "stopping")
var err error conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: r.port})
r.conn, err = net.ListenUDP("udp4", &net.UDPAddr{Port: r.port})
if err != nil { if err != nil {
l.Debugln(err) l.Debugln(err)
r.setError(err) r.setError(err)
return return
} }
defer r.conn.Close() defer conn.Close()
r.connMut.Lock()
r.conn = conn
r.connMut.Unlock()
bs := make([]byte, 65536) bs := make([]byte, 65536)
for { for {
n, addr, err := r.conn.ReadFrom(bs) n, addr, err := conn.ReadFrom(bs)
if err != nil { if err != nil {
l.Debugln(err) l.Debugln(err)
r.setError(err) r.setError(err)
@ -206,8 +221,12 @@ func (r *broadcastReader) Serve() {
} }
func (r *broadcastReader) Stop() { func (r *broadcastReader) Stop() {
r.connMut.Lock()
if r.conn != nil {
r.conn.Close() r.conn.Close()
} }
r.connMut.Unlock()
}
func (r *broadcastReader) String() string { func (r *broadcastReader) String() string {
return fmt.Sprintf("broadcastReader@%p", r) return fmt.Sprintf("broadcastReader@%p", r)

View File

@ -75,6 +75,7 @@ func NewSvc(cfg *config.Wrapper, tlsCfg *tls.Config) *Svc {
eventBc := &eventBroadcaster{ eventBc := &eventBroadcaster{
svc: svc, svc: svc,
stop: make(chan struct{}),
} }
svc.Add(receiver) svc.Add(receiver)