1package fdwait
2
3import (
4 "golang.org/x/sys/unix"
5 "testing"
6)
7
8// Closing a watched file removes it from epoll. Reusing its number must
9// register the new file, not leave it waiting on the old registration.
10func TestPollRecycledDescriptor(t *testing.T) {
11 p, err := New()
12 if err != nil {
13 t.Fatal(err)
14 }
15 defer p.Close()
16 fd, err := unix.Eventfd(0, unix.EFD_NONBLOCK|unix.EFD_CLOEXEC)
17 if err != nil {
18 t.Fatal(err)
19 }
20 fds := []unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN}}
21 if _, err := p.Poll(fds, 1); err != nil {
22 unix.Close(fd)
23 t.Fatal(err)
24 }
25 unix.Close(fd)
26 replacement, err := unix.Eventfd(0, unix.EFD_NONBLOCK|unix.EFD_CLOEXEC)
27 if err != nil {
28 t.Fatal(err)
29 }
30 defer unix.Close(replacement)
31 if replacement != fd {
32 t.Skip("descriptor number not reused")
33 }
34 if _, err := unix.Write(replacement, []byte{1, 0, 0, 0, 0, 0, 0, 0}); err != nil {
35 t.Fatal(err)
36 }
37 if n, err := p.Poll(fds, 1000); n != 1 || err != nil {
38 t.Fatalf("reused descriptor: %d %v", n, err)
39 }
40}
41
42func TestPollHangup(t *testing.T) {
43 p, err := New()
44 if err != nil {
45 t.Fatal(err)
46 }
47 defer p.Close()
48 var pipe [2]int
49 if err := unix.Pipe2(pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC); err != nil {
50 t.Fatal(err)
51 }
52 defer unix.Close(pipe[0])
53 unix.Close(pipe[1])
54 fds := []unix.PollFd{{Fd: int32(pipe[0]), Events: unix.POLLIN}}
55 if n, err := p.Poll(fds, 1000); n != 1 || err != nil || fds[0].Revents&unix.POLLHUP == 0 {
56 t.Fatalf("hangup: %d %v %+v", n, err, fds)
57 }
58}