Browse Source

Fix issue #74 - crash on reenabling previously invalid zone

This crash is similar to issue #69 but with a different cause (and different fix)

To replicate:
* Alter `dns/example.com` so it is invalid (e.g. put an `x` at the top)
* Start `geodns`
* Alter `dns/example.com` so it is valid (e.g. remove the inserted `x`)
* Wait for `geodns` to reload `example.com`
* Perform any `dig` query for that zone e.g. to `dig A weight.example.com @....`

This produces a panic at:

     z.Metrics.Queries.Mark(1)

on line 34 of `zone.go`, because z.Metrics is `{nil, nil, nil, nil}`.

This cause of this problem is that when the zone is first loaded, `Metrics` is initialised to `{nil, nil, nil, nil}`. `SetupMetrics` is never called because the zone is invalid, but the old zone is kept around (presumably because in more complex circumstances it could have useful metrics in which should not be zeroed. When the zone is made loadable, `old` is non-nil, so the previous `Metrics` `struct` is copied, but not initialised, so it remains `nil`. The fix (coming right up) is to initialise any `nil` members of the `Metrics` struct whatever the value of `old` on entry.

Signed-off-by: Alex Bligh <[email protected]>
Alex Bligh 10 years ago
parent
commit
b7a8e15a53
1 changed files with 9 additions and 2 deletions
  1. 9 2
      zone.go

+ 9 - 2
zone.go

@@ -80,12 +80,19 @@ func NewZone(name string) *Zone {
 func (z *Zone) SetupMetrics(old *Zone) {
 	if old != nil {
 		z.Metrics = old.Metrics
-	} else {
+	}
+	if z.Metrics.Queries == nil {
 		z.Metrics.Queries = metrics.NewMeter()
-		z.Metrics.EdnsQueries = metrics.NewMeter()
 		metrics.Register(z.Origin+" queries", z.Metrics.Queries)
+	}
+	if z.Metrics.EdnsQueries == nil {
+		z.Metrics.EdnsQueries = metrics.NewMeter()
 		metrics.Register(z.Origin+" EDNS queries", z.Metrics.EdnsQueries)
+	}
+	if z.Metrics.LabelStats == nil {
 		z.Metrics.LabelStats = NewZoneLabelStats(10000)
+	}
+	if z.Metrics.ClientStats == nil {
 		z.Metrics.ClientStats = NewZoneLabelStats(10000)
 	}
 }