Skip to content

Commit

Permalink
support fd_sync for stdio
Browse files Browse the repository at this point in the history
Signed-off-by: Rob Herley <[email protected]>
  • Loading branch information
robherley committed Jan 12, 2025
1 parent 610c202 commit 4f458ca
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
13 changes: 13 additions & 0 deletions internal/sys/stdio.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ func (f *writerFile) Write(buf []byte) (int, experimentalsys.Errno) {
return n, experimentalsys.UnwrapOSError(err)
}

// syncer is a writer that support flushing for fd_sync
type syncer interface {
Sync() error
}

// Sync implements the same method as documented on sys.File
func (f *writerFile) Sync() experimentalsys.Errno {
if s, ok := f.w.(syncer); ok {
return experimentalsys.UnwrapOSError(s.Sync())
}
return 0
}

// noopStdinFile is a fs.ModeDevice file for use implementing FdStdin. This is
// safer than reading from os.DevNull as it can never overrun operating system
// file descriptors.
Expand Down
62 changes: 62 additions & 0 deletions internal/sys/stdio_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package sys

import (
"bytes"
"io"
"io/fs"
"os"
"testing"
Expand Down Expand Up @@ -136,3 +138,63 @@ func TestStdio(t *testing.T) {
}
}
}

type syncable struct {
io.Writer
Syncd bool
}

func (s *syncable) Sync() error {
s.Syncd = true
return nil
}

func TestStdioSync(t *testing.T) {
tmpFile, err := os.CreateTemp(t.TempDir(), "anotherfile")
require.NoError(t, err)
defer tmpFile.Close()

syncbuf := &syncable{Writer: bytes.NewBuffer(nil)}

stdoutNil, err := stdioWriterFileEntry("stdout", nil)
require.NoError(t, err)

stdoutFile, err := stdioWriterFileEntry("stdout", tmpFile)
require.NoError(t, err)

stdoutSync, err := stdioWriterFileEntry("stdout", syncbuf)
require.NoError(t, err)

tests := []struct {
name string
f *FileEntry
}{
{
name: "nil",
f: stdoutNil,
},
{
name: "file",
f: stdoutFile,
},
{
name: "syncer",
f: stdoutSync,
},
}

for _, tt := range tests {
tc := tt

t.Run(tc.name, func(t *testing.T) {
_, errno := tc.f.File.Write([]byte("hello"))
require.EqualErrno(t, 0, errno)
errno = tc.f.File.Sync()
require.EqualErrno(t, 0, errno)

if tc.f == stdoutSync {
require.True(t, syncbuf.Syncd)
}
})
}
}

0 comments on commit 4f458ca

Please sign in to comment.