diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-12-03 13:40:02 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-12-09 16:01:47 +0100 |
commit | 450189162e15c813713b5c3a5208bdb6380c17f8 (patch) | |
tree | 40c4d93b70a705f50559a72aac135b6a6129336e /ringlogger | |
parent | manager: use service subscriptions on win 8+ (diff) | |
download | wireguard-windows-450189162e15c813713b5c3a5208bdb6380c17f8.tar.xz wireguard-windows-450189162e15c813713b5c3a5208bdb6380c17f8.zip |
ringlogger: hook into global panic writer
This is a grotesque hack, and hopefully upstream Go will provide a nicer
way of doing this, but already it seems quite adept at catching panics.
See https://github.com/golang/go/issues/42888 for more info.
This requires us to rewrite the ringlogger path to avoid all
allocations.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'ringlogger')
-rw-r--r-- | ringlogger/global.go | 35 | ||||
-rw-r--r-- | ringlogger/ringlogger.go | 29 |
2 files changed, 55 insertions, 9 deletions
diff --git a/ringlogger/global.go b/ringlogger/global.go index 0d99e5a0..6f4458ca 100644 --- a/ringlogger/global.go +++ b/ringlogger/global.go @@ -8,6 +8,7 @@ package ringlogger import ( "log" "path/filepath" + "unsafe" "golang.zx2c4.com/wireguard/windows/conf" ) @@ -28,5 +29,39 @@ func InitGlobalLogger(tag string) error { } log.SetOutput(Global) log.SetFlags(0) + overrideWrite = globalWrite return nil } + +//go:linkname overrideWrite runtime.overrideWrite +var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32 + +var globalBuffer [maxLogLineLength - 1 - maxTagLength - 3]byte +var globalBufferLocation int + +//go:nosplit +func globalWrite(fd uintptr, p unsafe.Pointer, n int32) int32 { + b := (*[1 << 30]byte)(p)[:n] + for len(b) > 0 { + amountAvailable := len(globalBuffer) - globalBufferLocation + amountToCopy := len(b) + if amountToCopy > amountAvailable { + amountToCopy = amountAvailable + } + copy(globalBuffer[globalBufferLocation:], b[:amountToCopy]) + b = b[amountToCopy:] + globalBufferLocation += amountToCopy + foundNl := false + for i := globalBufferLocation - amountToCopy; i < globalBufferLocation; i++ { + if globalBuffer[i] == '\n' { + foundNl = true + break + } + } + if foundNl || len(b) > 0 { + Global.Write(globalBuffer[:globalBufferLocation]) + globalBufferLocation = 0 + } + } + return n +} diff --git a/ringlogger/ringlogger.go b/ringlogger/ringlogger.go index 84eb2fcc..fda4ddd9 100644 --- a/ringlogger/ringlogger.go +++ b/ringlogger/ringlogger.go @@ -21,6 +21,7 @@ import ( const ( maxLogLineLength = 512 + maxTagLength = 5 maxLines = 2048 magic = 0xbadbabe ) @@ -45,6 +46,9 @@ type Ringlogger struct { } func NewRinglogger(filename string, tag string) (*Ringlogger, error) { + if len(tag) > maxTagLength { + return nil, windows.ERROR_LABEL_TOO_LONG + } file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) if err != nil { return nil, err @@ -106,6 +110,11 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) { if rl.readOnly { return 0, io.ErrShortWrite } + ret := len(p) + p = bytes.TrimSpace(p) + if len(p) == 0 { + return ret, nil + } // Race: This isn't synchronized with the fetch_add below, so items might be slightly out of order. ts := time.Now().UnixNano() @@ -124,18 +133,20 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) { line.line[i] = 0 } - text := []byte(fmt.Sprintf("[%s] %s", rl.tag, bytes.TrimSpace(p))) - if len(text) > maxLogLineLength-1 { - text = text[:maxLogLineLength-1] + textLen := 3 + len(p) + len(rl.tag) + if textLen > maxLogLineLength-1 { + p = p[:maxLogLineLength-1-3-len(rl.tag)] } - line.line[len(text)] = 0 - copy(line.line[:], text[:]) + line.line[textLen] = 0 + line.line[0] = 0 // Null out the beginning and only let it extend after the other writes have completed + copy(line.line[1:], rl.tag) + line.line[1+len(rl.tag)] = ']' + line.line[2+len(rl.tag)] = ' ' + copy(line.line[3+len(rl.tag):], p[:]) + line.line[0] = '[' atomic.StoreInt64(&line.timeNs, ts) - windows.FlushViewOfFile((uintptr)(unsafe.Pointer(&rl.log.nextIndex)), unsafe.Sizeof(rl.log.nextIndex)) - windows.FlushViewOfFile((uintptr)(unsafe.Pointer(line)), unsafe.Sizeof(*line)) - - return len(p), nil + return ret, nil } func (rl *Ringlogger) WriteTo(out io.Writer) (n int64, err error) { |