pkg/log: fix data race on d (#2698)
* pkg/log: fix data race on d Wrap d in a mutex to prevent data race. This makes is slower, but this is a debugging aid anyway. It's not used normally. Signed-off-by: Miek Gieben <miek@miek.nl> * Fix tests compilation Signed-off-by: Miek Gieben <miek@miek.nl> * Fix test compile Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
parent
118b0c9408
commit
a84413bd07
6 changed files with 47 additions and 26 deletions
|
@ -62,7 +62,7 @@ func NewServer(addr string, group []*Config) (*Server, error) {
|
||||||
for _, site := range group {
|
for _, site := range group {
|
||||||
if site.Debug {
|
if site.Debug {
|
||||||
s.debug = true
|
s.debug = true
|
||||||
log.D = true
|
log.D.Set()
|
||||||
}
|
}
|
||||||
// set the config per zone
|
// set the config per zone
|
||||||
s.zones[site.Zone] = site
|
s.zones[site.Zone] = site
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
//
|
//
|
||||||
// msg will prefix the pcap dump.
|
// msg will prefix the pcap dump.
|
||||||
func Hexdump(m *dns.Msg, v ...interface{}) {
|
func Hexdump(m *dns.Msg, v ...interface{}) {
|
||||||
if !log.D {
|
if !log.D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func Hexdump(m *dns.Msg, v ...interface{}) {
|
||||||
|
|
||||||
// Hexdumpf dumps a DNS message as Hexdump, but allows a format string.
|
// Hexdumpf dumps a DNS message as Hexdump, but allows a format string.
|
||||||
func Hexdumpf(m *dns.Msg, format string, v ...interface{}) {
|
func Hexdumpf(m *dns.Msg, format string, v ...interface{}) {
|
||||||
if !log.D {
|
if !log.D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,21 @@ func msg() *dns.Msg {
|
||||||
m.SetQuestion("example.local.", dns.TypeA)
|
m.SetQuestion("example.local.", dns.TypeA)
|
||||||
m.SetEdns0(4096, true)
|
m.SetEdns0(4096, true)
|
||||||
m.Id = 10
|
m.Id = 10
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNoDebug(t *testing.T) {
|
||||||
|
// Must come first, because set log.D.Set() which is impossible to undo.
|
||||||
|
var f bytes.Buffer
|
||||||
|
golog.SetOutput(&f)
|
||||||
|
|
||||||
|
str := "Hi There!"
|
||||||
|
Hexdumpf(msg(), "%s %d", str, 10)
|
||||||
|
if len(f.Bytes()) != 0 {
|
||||||
|
t.Errorf("Expected no output, got %d bytes", len(f.Bytes()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleLogHexdump() {
|
func ExampleLogHexdump() {
|
||||||
buf, _ := msg().Pack()
|
buf, _ := msg().Pack()
|
||||||
h := hexdump(buf)
|
h := hexdump(buf)
|
||||||
|
@ -36,7 +47,7 @@ func ExampleLogHexdump() {
|
||||||
func TestHexdump(t *testing.T) {
|
func TestHexdump(t *testing.T) {
|
||||||
var f bytes.Buffer
|
var f bytes.Buffer
|
||||||
golog.SetOutput(&f)
|
golog.SetOutput(&f)
|
||||||
log.D = true
|
log.D.Set()
|
||||||
|
|
||||||
str := "Hi There!"
|
str := "Hi There!"
|
||||||
Hexdump(msg(), str)
|
Hexdump(msg(), str)
|
||||||
|
@ -50,7 +61,7 @@ func TestHexdump(t *testing.T) {
|
||||||
func TestHexdumpf(t *testing.T) {
|
func TestHexdumpf(t *testing.T) {
|
||||||
var f bytes.Buffer
|
var f bytes.Buffer
|
||||||
golog.SetOutput(&f)
|
golog.SetOutput(&f)
|
||||||
log.D = true
|
log.D.Set()
|
||||||
|
|
||||||
str := "Hi There!"
|
str := "Hi There!"
|
||||||
Hexdumpf(msg(), "%s %d", str, 10)
|
Hexdumpf(msg(), "%s %d", str, 10)
|
||||||
|
@ -60,15 +71,3 @@ func TestHexdumpf(t *testing.T) {
|
||||||
t.Errorf("The string %s %d, is not contained in the logged output: %s", str, 10, logged)
|
t.Errorf("The string %s %d, is not contained in the logged output: %s", str, 10, logged)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoDebug(t *testing.T) {
|
|
||||||
var f bytes.Buffer
|
|
||||||
golog.SetOutput(&f)
|
|
||||||
log.D = false
|
|
||||||
|
|
||||||
str := "Hi There!"
|
|
||||||
Hexdumpf(msg(), "%s %d", str, 10)
|
|
||||||
if len(f.Bytes()) != 0 {
|
|
||||||
t.Errorf("Expected no output, got %d bytes", len(f.Bytes()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,11 +13,33 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
golog "log"
|
golog "log"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// D controls whether we should output debug logs. If true, we do.
|
// D controls whether we should output debug logs. If true, we do, once set
|
||||||
var D bool
|
// it can not be unset.
|
||||||
|
var D = &d{}
|
||||||
|
|
||||||
|
type d struct {
|
||||||
|
on bool
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets d to true.
|
||||||
|
func (d *d) Set() {
|
||||||
|
d.Lock()
|
||||||
|
d.on = true
|
||||||
|
d.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value return the boolean value of d.
|
||||||
|
func (d *d) Value() bool {
|
||||||
|
d.RLock()
|
||||||
|
b := d.on
|
||||||
|
d.RUnlock()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// RFC3339Milli doesn't exist, invent it here.
|
// RFC3339Milli doesn't exist, invent it here.
|
||||||
func clock() string { return time.Now().Format("2006-01-02T15:04:05.000Z07:00") }
|
func clock() string { return time.Now().Format("2006-01-02T15:04:05.000Z07:00") }
|
||||||
|
@ -35,7 +57,7 @@ func log(level string, v ...interface{}) {
|
||||||
// Debug is equivalent to log.Print(), but prefixed with "[DEBUG] ". It only outputs something
|
// Debug is equivalent to log.Print(), but prefixed with "[DEBUG] ". It only outputs something
|
||||||
// if D is true.
|
// if D is true.
|
||||||
func Debug(v ...interface{}) {
|
func Debug(v ...interface{}) {
|
||||||
if !D {
|
if !D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log(debug, v...)
|
log(debug, v...)
|
||||||
|
@ -44,7 +66,7 @@ func Debug(v ...interface{}) {
|
||||||
// Debugf is equivalent to log.Printf(), but prefixed with "[DEBUG] ". It only outputs something
|
// Debugf is equivalent to log.Printf(), but prefixed with "[DEBUG] ". It only outputs something
|
||||||
// if D is true.
|
// if D is true.
|
||||||
func Debugf(format string, v ...interface{}) {
|
func Debugf(format string, v ...interface{}) {
|
||||||
if !D {
|
if !D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logf(debug, format, v...)
|
logf(debug, format, v...)
|
||||||
|
|
|
@ -18,7 +18,7 @@ func TestDebug(t *testing.T) {
|
||||||
}
|
}
|
||||||
f.Reset()
|
f.Reset()
|
||||||
|
|
||||||
D = true
|
D.Set()
|
||||||
Debug("debug")
|
Debug("debug")
|
||||||
if x := f.String(); !strings.Contains(x, debug+"debug") {
|
if x := f.String(); !strings.Contains(x, debug+"debug") {
|
||||||
t.Errorf("Expected debug log to be %s, got %s", debug+"debug", x)
|
t.Errorf("Expected debug log to be %s, got %s", debug+"debug", x)
|
||||||
|
@ -29,7 +29,7 @@ func TestDebugx(t *testing.T) {
|
||||||
var f bytes.Buffer
|
var f bytes.Buffer
|
||||||
golog.SetOutput(&f)
|
golog.SetOutput(&f)
|
||||||
|
|
||||||
D = true
|
D.Set()
|
||||||
|
|
||||||
Debugf("%s", "debug")
|
Debugf("%s", "debug")
|
||||||
if x := f.String(); !strings.Contains(x, debug+"debug") {
|
if x := f.String(); !strings.Contains(x, debug+"debug") {
|
||||||
|
|
|
@ -24,7 +24,7 @@ func (p P) log(level string, v ...interface{}) {
|
||||||
|
|
||||||
// Debug logs as log.Debug.
|
// Debug logs as log.Debug.
|
||||||
func (p P) Debug(v ...interface{}) {
|
func (p P) Debug(v ...interface{}) {
|
||||||
if !D {
|
if !D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.log(debug, v...)
|
p.log(debug, v...)
|
||||||
|
@ -32,7 +32,7 @@ func (p P) Debug(v ...interface{}) {
|
||||||
|
|
||||||
// Debugf logs as log.Debugf.
|
// Debugf logs as log.Debugf.
|
||||||
func (p P) Debugf(format string, v ...interface{}) {
|
func (p P) Debugf(format string, v ...interface{}) {
|
||||||
if !D {
|
if !D.Value() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.logf(debug, format, v...)
|
p.logf(debug, format, v...)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue