Skip to content

Commit e72d58b

Browse files
fix: guard server log lumberjack with mutex (coder#15582)
(Hopefully) closes coder/internal#213.
1 parent 029cd5d commit e72d58b

File tree

2 files changed

+33
-32
lines changed

2 files changed

+33
-32
lines changed

cli/agent.go

+3-30
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"runtime"
1313
"strconv"
1414
"strings"
15-
"sync"
1615
"time"
1716

1817
"cloud.google.com/go/compute/metadata"
@@ -30,6 +29,7 @@ import (
3029
"github.com/coder/coder/v2/agent/agentssh"
3130
"github.com/coder/coder/v2/agent/reaper"
3231
"github.com/coder/coder/v2/buildinfo"
32+
"github.com/coder/coder/v2/cli/clilog"
3333
"github.com/coder/coder/v2/codersdk"
3434
"github.com/coder/coder/v2/codersdk/agentsdk"
3535
"github.com/coder/serpent"
@@ -110,7 +110,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
110110
// Spawn a reaper so that we don't accumulate a ton
111111
// of zombie processes.
112112
if reaper.IsInitProcess() && !noReap && isLinux {
113-
logWriter := &lumberjackWriteCloseFixer{w: &lumberjack.Logger{
113+
logWriter := &clilog.LumberjackWriteCloseFixer{Writer: &lumberjack.Logger{
114114
Filename: filepath.Join(logDir, "coder-agent-init.log"),
115115
MaxSize: 5, // MB
116116
// Without this, rotated logs will never be deleted.
@@ -153,7 +153,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
153153
// reaper.
154154
go DumpHandler(ctx, "agent")
155155

156-
logWriter := &lumberjackWriteCloseFixer{w: &lumberjack.Logger{
156+
logWriter := &clilog.LumberjackWriteCloseFixer{Writer: &lumberjack.Logger{
157157
Filename: filepath.Join(logDir, "coder-agent.log"),
158158
MaxSize: 5, // MB
159159
// Per customer incident on November 17th, 2023, its helpful
@@ -478,33 +478,6 @@ func ServeHandler(ctx context.Context, logger slog.Logger, handler http.Handler,
478478
}
479479
}
480480

481-
// lumberjackWriteCloseFixer is a wrapper around an io.WriteCloser that
482-
// prevents writes after Close. This is necessary because lumberjack
483-
// re-opens the file on Write.
484-
type lumberjackWriteCloseFixer struct {
485-
w io.WriteCloser
486-
mu sync.Mutex // Protects following.
487-
closed bool
488-
}
489-
490-
func (c *lumberjackWriteCloseFixer) Close() error {
491-
c.mu.Lock()
492-
defer c.mu.Unlock()
493-
494-
c.closed = true
495-
return c.w.Close()
496-
}
497-
498-
func (c *lumberjackWriteCloseFixer) Write(p []byte) (int, error) {
499-
c.mu.Lock()
500-
defer c.mu.Unlock()
501-
502-
if c.closed {
503-
return 0, io.ErrClosedPipe
504-
}
505-
return c.w.Write(p)
506-
}
507-
508481
// extractPort handles different url strings.
509482
// - localhost:6060
510483
// - http://localhost:6060

cli/clilog/clilog.go

+30-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"regexp"
88
"strings"
9+
"sync"
910

1011
"golang.org/x/xerrors"
1112
"gopkg.in/natefinch/lumberjack.v2"
@@ -111,12 +112,12 @@ func (b *Builder) Build(inv *serpent.Invocation) (log slog.Logger, closeLog func
111112
sinks = append(sinks, sinkFn(inv.Stderr))
112113

113114
default:
114-
logWriter := &lumberjack.Logger{
115+
logWriter := &LumberjackWriteCloseFixer{Writer: &lumberjack.Logger{
115116
Filename: loc,
116117
MaxSize: 5, // MB
117118
// Without this, rotated logs will never be deleted.
118119
MaxBackups: 1,
119-
}
120+
}}
120121
closers = append(closers, logWriter.Close)
121122
sinks = append(sinks, sinkFn(logWriter))
122123
}
@@ -210,3 +211,30 @@ func (f *debugFilterSink) Sync() {
210211
sink.Sync()
211212
}
212213
}
214+
215+
// LumberjackWriteCloseFixer is a wrapper around an io.WriteCloser that
216+
// prevents writes after Close. This is necessary because lumberjack
217+
// re-opens the file on Write.
218+
type LumberjackWriteCloseFixer struct {
219+
Writer io.WriteCloser
220+
mu sync.Mutex // Protects following.
221+
closed bool
222+
}
223+
224+
func (c *LumberjackWriteCloseFixer) Close() error {
225+
c.mu.Lock()
226+
defer c.mu.Unlock()
227+
228+
c.closed = true
229+
return c.Writer.Close()
230+
}
231+
232+
func (c *LumberjackWriteCloseFixer) Write(p []byte) (int, error) {
233+
c.mu.Lock()
234+
defer c.mu.Unlock()
235+
236+
if c.closed {
237+
return 0, io.ErrClosedPipe
238+
}
239+
return c.Writer.Write(p)
240+
}

0 commit comments

Comments
 (0)