Skip to content

Commit 38c5469

Browse files
committed
Only close epoller FD at most once.
Previously, multiple calls to epoller.Close() could result in unix.Close being called on the same FD value multiple times. This made it easy for consumers to create race conditions where calls to Close after the first one were closing unrelated FDs in the process that happened to use the same value of the epoller FD. This change uses sync.Once to ensure that unix.Close is only called once, with subsequent calls to Close returning "file already closed" instead. Signed-off-by: Erik Sipsma <[email protected]>
1 parent 02ecf6a commit 38c5469

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

console_linux.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type Epoller struct {
5858
efd int
5959
mu sync.Mutex
6060
fdMapping map[int]*EpollConsole
61+
closeOnce sync.Once
6162
}
6263

6364
// NewEpoller returns an instance of epoller with a valid epoll fd.
@@ -151,7 +152,11 @@ func (e *Epoller) getConsole(sysfd int) *EpollConsole {
151152

152153
// Close closes the epoll fd
153154
func (e *Epoller) Close() error {
154-
return unix.Close(e.efd)
155+
closeErr := os.ErrClosed // default to "file already closed"
156+
e.closeOnce.Do(func() {
157+
closeErr = unix.Close(e.efd)
158+
})
159+
return closeErr
155160
}
156161

157162
// EpollConsole acts like a console but registers its file descriptor with an

console_linux_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,12 @@ func TestEpollConsole(t *testing.T) {
8585
if out := b.String(); out != expectedOutput {
8686
t.Errorf("unexpected output %q", out)
8787
}
88+
89+
// make sure multiple Close calls return os.ErrClosed after the first
90+
if err := epoller.Close(); err != nil {
91+
t.Fatal(err)
92+
}
93+
if err := epoller.Close(); err != os.ErrClosed {
94+
t.Fatalf("unexpected error returned from second call to epoller.Close(): %v", err)
95+
}
8896
}

0 commit comments

Comments
 (0)