Commit 1f90447e authored by Roger Peppe's avatar Roger Peppe Committed by Rob Pike

log: ensure writes are atomic.

This means that any Writer can be used safely
even when Output is called concurrently.
Fixes #1302.

R=r, nigeltao_gnome
CC=golang-dev
https://golang.org/cl/3300042
parent b06dc26a
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"runtime" "runtime"
"os" "os"
"time" "time"
"sync"
) )
// These flags define which text to prefix to each log entry generated by the Logger. // These flags define which text to prefix to each log entry generated by the Logger.
...@@ -34,8 +35,12 @@ const ( ...@@ -34,8 +35,12 @@ const (
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
) )
// Logger represents an active logging object. // A Logger represents an active logging object that generates lines of
// output to an io.Writer. Each logging operation makes a single call to
// the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct { type Logger struct {
mu sync.Mutex // ensures atomic writes
out io.Writer // destination for output out io.Writer // destination for output
prefix string // prefix to write at beginning of each line prefix string // prefix to write at beginning of each line
flag int // properties flag int // properties
...@@ -46,7 +51,7 @@ type Logger struct { ...@@ -46,7 +51,7 @@ type Logger struct {
// The prefix appears at the beginning of each generated log line. // The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties. // The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) *Logger { func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out, prefix, flag} return &Logger{out: out, prefix: prefix, flag: flag}
} }
var std = New(os.Stderr, "", Ldate|Ltime) var std = New(os.Stderr, "", Ldate|Ltime)
...@@ -139,6 +144,8 @@ func (l *Logger) Output(calldepth int, s string) os.Error { ...@@ -139,6 +144,8 @@ func (l *Logger) Output(calldepth int, s string) os.Error {
if len(s) > 0 && s[len(s)-1] != '\n' { if len(s) > 0 && s[len(s)-1] != '\n' {
buf.WriteByte('\n') buf.WriteByte('\n')
} }
l.mu.Lock()
defer l.mu.Unlock()
_, err := l.out.Write(buf.Bytes()) _, err := l.out.Write(buf.Bytes())
return err return err
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment