Skip to content

Commit 8191438

Browse files
authored
fix: ensure (Logger).exit is non-nil before calling (#132)
On an empty logger (which we use), it's possible for (Logger).Fatal to panic when attempting to call exit. This ensures that `l.exit` isn't nil before calling it.
1 parent 930b877 commit 8191438

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

slog.go

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"go.opencensus.io/trace"
2222
)
2323

24+
var defaultExitFn = os.Exit
25+
2426
// Sink is the destination of a Logger.
2527
//
2628
// All sinks must be safe for concurrent use.
@@ -114,6 +116,11 @@ func (l Logger) Critical(ctx context.Context, msg string, fields ...Field) {
114116
func (l Logger) Fatal(ctx context.Context, msg string, fields ...Field) {
115117
l.log(ctx, LevelFatal, msg, fields)
116118
l.Sync()
119+
120+
if l.exit == nil {
121+
l.exit = defaultExitFn
122+
}
123+
117124
l.exit(1)
118125
}
119126

slog_exit_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package slog
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"cdr.dev/slog/internal/assert"
8+
)
9+
10+
func TestExit(t *testing.T) {
11+
// This can't be parallel since it modifies a global variable.
12+
t.Run("defaultExitFn", func(t *testing.T) {
13+
var (
14+
ctx = context.Background()
15+
log Logger
16+
defaultExitFnCalled bool
17+
)
18+
19+
prevExitFn := defaultExitFn
20+
t.Cleanup(func() { defaultExitFn = prevExitFn })
21+
22+
defaultExitFn = func(_ int) {
23+
defaultExitFnCalled = true
24+
}
25+
26+
log.Debug(ctx, "hi")
27+
log.Info(ctx, "hi")
28+
log.Warn(ctx, "hi")
29+
log.Error(ctx, "hi")
30+
log.Critical(ctx, "hi")
31+
log.Fatal(ctx, "hi")
32+
33+
assert.True(t, "default exit fn used", defaultExitFnCalled)
34+
})
35+
}

0 commit comments

Comments
 (0)