aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ringlogger
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-12-03 13:40:02 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-12-09 16:01:47 +0100
commit450189162e15c813713b5c3a5208bdb6380c17f8 (patch)
tree40c4d93b70a705f50559a72aac135b6a6129336e /ringlogger
parentmanager: use service subscriptions on win 8+ (diff)
downloadwireguard-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.go35
-rw-r--r--ringlogger/ringlogger.go29
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) {