From c05b06a12d005f50e4776095a60d6bd9c2c91fac Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 10 Feb 2017 15:17:38 -0800 Subject: os: use poller for file I/O This changes the os package to use the runtime poller for file I/O where possible. When a system call blocks on a pollable descriptor, the goroutine will be blocked on the poller but the thread will be released to run other goroutines. When using a non-pollable descriptor, the os package will continue to use thread-blocking system calls as before. For example, on GNU/Linux, the runtime poller uses epoll. epoll does not support ordinary disk files, so they will continue to use blocking I/O as before. The poller will be used for pipes. Since this means that the poller is used for many more programs, this modifies the runtime to only block waiting for the poller if there is some goroutine that is waiting on the poller. Otherwise, there is no point, as the poller will never make any goroutine ready. This preserves the runtime's current simple deadlock detection. This seems to crash FreeBSD systems, so it is disabled on FreeBSD. This is issue 19093. Using the poller on Windows requires opening the file with FILE_FLAG_OVERLAPPED. We should only do that if we can remove that flag if the program calls the Fd method. This is issue 19098. Update #6817. Update #7903. Update #15021. Update #18507. Update #19093. Update #19098. Change-Id: Ia5197dcefa7c6fbcca97d19a6f8621b2abcbb1fe Reviewed-on: https://go-review.googlesource.com/36800 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Russ Cox --- src/os/exec/exec_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/os/exec/exec_test.go') diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 34337450a0..1a159e261f 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -12,6 +12,7 @@ import ( "bytes" "context" "fmt" + "internal/poll" "internal/testenv" "io" "io/ioutil" @@ -369,12 +370,16 @@ var testedAlreadyLeaked = false // basefds returns the number of expected file descriptors // to be present in a process at start. +// stdin, stdout, stderr, epoll/kqueue func basefds() uintptr { return os.Stderr.Fd() + 1 } func closeUnexpectedFds(t *testing.T, m string) { for fd := basefds(); fd <= 101; fd++ { + if fd == poll.PollDescriptor() { + continue + } err := os.NewFile(fd, "").Close() if err == nil { t.Logf("%s: Something already leaked - closed fd %d", m, fd) @@ -732,6 +737,9 @@ func TestHelperProcess(*testing.T) { // Now verify that there are no other open fds. var files []*os.File for wantfd := basefds() + 1; wantfd <= 100; wantfd++ { + if wantfd == poll.PollDescriptor() { + continue + } f, err := os.Open(os.Args[0]) if err != nil { fmt.Printf("error opening file with expected fd %d: %v", wantfd, err) -- cgit v1.3