]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll: consolidate cancelIO logic into waitIO
authorqmuntal <quimmuntal@gmail.com>
Fri, 30 Jan 2026 12:29:10 +0000 (13:29 +0100)
committerQuim Muntal <quimmuntal@gmail.com>
Mon, 2 Feb 2026 18:51:25 +0000 (10:51 -0800)
This is a step towards deferring adding the handle to IOCP until the
first IO operation.

The main goal of this CL is to remove the fd.pollable() check in
cancelIO.

For #76391

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest,gotip-windows-amd64-race
Change-Id: I76263ce12980297d88a5f6c514e4074dfee428cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/740540
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
src/internal/poll/fd_windows.go

index edad6563508bc6471d200a2894ee2b11fdb93edc..ef8050daf42932d3140378e9791ea5bf55f55095 100644 (file)
@@ -198,7 +198,8 @@ var operationPool = sync.Pool{
        },
 }
 
-// waitIO waits for the IO operation o to complete.
+// waitIO waits for the IO operation to complete,
+// handling cancellation if necessary.
 func (fd *FD) waitIO(o *operation) error {
        if fd.isBlocking {
                panic("can't wait on blocking operations")
@@ -213,29 +214,24 @@ func (fd *FD) waitIO(o *operation) error {
        // Wait for our request to complete.
        err := fd.pd.wait(int(o.mode), fd.isFile)
        switch err {
-       case nil, ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
-               // No other error is expected.
+       case nil:
+               // IO completed successfully.
+       case ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
+               // IO interrupted by "close" or "timeout", cancel our request.
+               // ERROR_NOT_FOUND can be returned when the request succeded
+               // between the time wait returned and CancelIoEx was executed.
+               if err := syscall.CancelIoEx(fd.Sysfd, &o.o); err != nil && err != syscall.ERROR_NOT_FOUND {
+                       // TODO(brainman): maybe do something else, but panic.
+                       panic(err)
+               }
+               fd.pd.waitCanceled(int(o.mode))
        default:
+               // No other error is expected.
                panic("unexpected runtime.netpoll error: " + err.Error())
        }
        return err
 }
 
-// cancelIO cancels the IO operation o and waits for it to complete.
-func (fd *FD) cancelIO(o *operation) {
-       if !fd.pollable() {
-               return
-       }
-       // Cancel our request.
-       err := syscall.CancelIoEx(fd.Sysfd, &o.o)
-       // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
-       if err != nil && err != syscall.ERROR_NOT_FOUND {
-               // TODO(brainman): maybe do something else, but panic.
-               panic(err)
-       }
-       fd.pd.waitCanceled(int(o.mode))
-}
-
 // pin pins ptr for the duration of the IO operation.
 // If fd is in blocking mode, pin does nothing.
 func (fd *FD) pin(mode int, ptr any) {
@@ -295,12 +291,6 @@ func (fd *FD) execIO(mode int, submit func(o *operation) (uint32, error)) (int,
                // IO started asynchronously or completed synchronously but
                // a sync notification is required. Wait for it to complete.
                waitErr = fd.waitIO(o)
-               if waitErr != nil {
-                       // IO interrupted by "close" or "timeout".
-                       fd.cancelIO(o)
-                       // We issued a cancellation request, but the IO operation may still succeeded
-                       // before the cancellation request runs.
-               }
                if fd.isFile {
                        err = windows.GetOverlappedResult(fd.Sysfd, &o.o, &qty, false)
                } else {