File tree Expand file tree Collapse file tree 2 files changed +48
-3
lines changed Expand file tree Collapse file tree 2 files changed +48
-3
lines changed Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import (
1212 "reflect"
1313 "strconv"
1414 "strings"
15+ "syscall"
1516 "time"
1617 "unicode"
1718
@@ -224,9 +225,25 @@ func isTTY(w io.Writer) bool {
224225 if w == forceColorWriter {
225226 return true
226227 }
227- f , ok := w .(interface {
228- Fd () uintptr
229- })
228+ // SyscallConn is safe during file close.
229+ if sc , ok := w .(interface {
230+ SyscallConn () (syscall.RawConn , error )
231+ }); ok {
232+ conn , err := sc .SyscallConn ()
233+ if err != nil {
234+ return false
235+ }
236+ var isTerm bool
237+ err = conn .Control (func (fd uintptr ) {
238+ isTerm = term .IsTerminal (int (fd ))
239+ })
240+ if err != nil {
241+ return false
242+ }
243+ return isTerm
244+ }
245+ // Fallback to unsafe Fd.
246+ f , ok := w .(interface { Fd () uintptr })
230247 return ok && term .IsTerminal (int (f .Fd ()))
231248}
232249
Original file line number Diff line number Diff line change @@ -178,6 +178,34 @@ func TestEntry(t *testing.T) {
178178 assert .Equal (t , "entry matches" , string (wantByt ), gotBuf .String ())
179179 })
180180 }
181+
182+ t .Run ("isTTY during file close" , func (t * testing.T ) {
183+ t .Parallel ()
184+
185+ tmpdir := t .TempDir ()
186+ f , err := os .CreateTemp (tmpdir , "slog" )
187+ if err != nil {
188+ t .Fatal (err )
189+ }
190+ defer f .Close ()
191+
192+ done := make (chan struct {}, 2 )
193+ go func () {
194+ entryhuman .Fmt (new (bytes.Buffer ), f , slog.SinkEntry {
195+ Level : slog .LevelCritical ,
196+ Fields : slog .M (
197+ slog .F ("hey" , "hi" ),
198+ ),
199+ })
200+ done <- struct {}{}
201+ }()
202+ go func () {
203+ _ = f .Close ()
204+ done <- struct {}{}
205+ }()
206+ <- done
207+ <- done
208+ })
181209}
182210
183211func BenchmarkFmt (b * testing.B ) {
You can’t perform that action at this time.
0 commit comments