Browse Source

Error handling

Jakob Borg 12 years ago
parent
commit
f774b0a5dc
3 changed files with 27 additions and 8 deletions
  1. 21 5
      discover/discover.go
  2. 6 0
      protocol/protocol.go
  3. 0 3
      walk.go

+ 21 - 5
discover/discover.go

@@ -30,6 +30,7 @@ package discover
 import (
 	"encoding/binary"
 	"fmt"
+	"log"
 	"net"
 	"sync"
 	"time"
@@ -45,6 +46,11 @@ type Discoverer struct {
 	registryLock sync.RWMutex
 }
 
+// We tolerate a certain amount of errors because we might be running in
+// laptops that sleep and wake, have intermittent network connectivity, etc.
+// When we hit this many errors in succession, we stop.
+const maxErrors = 30
+
 func NewDiscoverer(id string, port int) (*Discoverer, error) {
 	local4 := &net.UDPAddr{IP: net.IP{0, 0, 0, 0}, Port: 21025}
 	conn, err := net.ListenUDP("udp4", local4)
@@ -77,22 +83,31 @@ func (d *Discoverer) sendAnnouncements() {
 	binary.BigEndian.PutUint16(buf[6:], uint16(len(idbs)))
 	copy(buf[8:], idbs)
 
-	for {
-		_, _, err := d.conn.WriteMsgUDP(buf, nil, remote4)
+	var errCounter = 0
+	var err error
+	for errCounter < maxErrors {
+		_, _, err = d.conn.WriteMsgUDP(buf, nil, remote4)
 		if err != nil {
-			panic(err)
+			errCounter++
+		} else {
+			errCounter = 0
 		}
 		time.Sleep(d.BroadcastIntv)
 	}
+	log.Println("discover/write: stopping due to too many errors:", err)
 }
 
 func (d *Discoverer) recvAnnouncements() {
 	var buf = make([]byte, 1024)
-	for {
+	var errCounter = 0
+	var err error
+	for errCounter < maxErrors {
 		_, addr, err := d.conn.ReadFromUDP(buf)
 		if err != nil {
-			panic(err)
+			time.Sleep(time.Second)
+			continue
 		}
+		errCounter = 0
 		magic := binary.BigEndian.Uint32(buf)
 		if magic != 0x121025 {
 			continue
@@ -111,6 +126,7 @@ func (d *Discoverer) recvAnnouncements() {
 			d.registryLock.Unlock()
 		}
 	}
+	log.Println("discover/read: stopping due to too many errors:", err)
 }
 
 func (d *Discoverer) Lookup(node string) (string, bool) {

+ 6 - 0
protocol/protocol.go

@@ -188,6 +188,9 @@ func (c *Connection) readerLoop() {
 
 		case messageTypeRequest:
 			c.processRequest(hdr.msgID)
+			if c.mreader.err != nil || c.mwriter.err != nil {
+				c.close()
+			}
 
 		case messageTypeResponse:
 			data := c.mreader.readResponse()
@@ -214,6 +217,9 @@ func (c *Connection) readerLoop() {
 			c.mwriter.writeUint32(encodeHeader(header{0, hdr.msgID, messageTypePong}))
 			c.flush()
 			c.wLock.Unlock()
+			if c.mwriter.err != nil {
+				c.close()
+			}
 
 		case messageTypePong:
 			c.wLock.RLock()

+ 0 - 3
walk.go

@@ -111,9 +111,6 @@ func Walk(dir string, model *Model, followSymlinks bool) []File {
 		d.Close()
 		for _, fi := range fis {
 			if fi.Mode()&os.ModeSymlink != 0 {
-				if traceFile {
-					debugf("Following symlink %q", fi.Name())
-				}
 				err := filepath.Walk(path.Join(dir, fi.Name())+"/", fn)
 				if err != nil {
 					warnln(err)