Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: Accept() blocks forever, timeout setting doesn't work on Windows XP SP3 #23375

Closed
ko80 opened this issue Jan 8, 2018 · 8 comments

Comments

Projects
None yet
4 participants
@ko80
Copy link

commented Jan 8, 2018

What version of Go are you using (go version)?

go1.9.2

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

windows/386

What did you do?

I faced a critical issue while using go1.9.2 windows/386 on Windows XP SP3. The trouble is that Accept() blocks forever even if I set a timeout using SetDeadline(). It blocks forever until the program exits. I consider it critical because I can't stop listeners when I need to. Additionally, conn.Read() blocks forever as well, but I didn't include it to the example to make is simpler.

In contrast, when I run this program on Windows 7 under VirtualBox (on the same Windows XP SP3), Accept() successfully unblocks after a timeout period.

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {

	listener, err := net.Listen("tcp", ":8888")
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	tcplistener := listener.(*net.TCPListener)
	tcplistener.SetDeadline(time.Now().Add(time.Second * 2))

	fmt.Println("Listener started")

	go func() {

		defer func() {
			tcplistener.Close()
			fmt.Println("Listener closed")
		}()

		for {

			conn, err := listener.Accept()
			if err != nil {
				fmt.Println(err.Error())
				return
			}

			conn.Write([]byte("OK\n"))
			conn.Close()

		}

	}()

	time.Sleep(time.Second * 10)

	fmt.Println("Exit")
}

What did you expect to see?

Terminal output (Windows 7):

Listener started
accept tcp [::]:8888 i/o timeout
Listener closed
Exit

What did you see instead?

Terminal output (Windows XP SP3):

Listener started
Exit

@ko80 ko80 changed the title Golang net package: Accept() timeout setting doesn't work on Windows XP SP3 net: Accept() timeout setting doesn't work on Windows XP SP3 Jan 8, 2018

@ALTree

This comment has been minimized.

Copy link
Member

commented Jan 8, 2018

@ko80

This comment has been minimized.

Copy link
Author

commented Jan 8, 2018

I've just tried to compile it on a previous stable version (go1.8.5 windows/386). The issue is the same.

@ianlancetaylor ianlancetaylor added this to the Go1.11 milestone Jan 8, 2018

@ko80 ko80 changed the title net: Accept() timeout setting doesn't work on Windows XP SP3 net: Accept() blocks forever, timeout setting doesn't work on Windows XP SP3 Jan 8, 2018

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 8, 2018

The first step to fixing this issue is understanding what a fix might look like. I assume that Windows XP does not support CancelIoEx. In that case the Go code should use CancelIo to cancel the call. Why does this not work for AcceptEx? Does XP provide a way to set a deadline for a call to AcceptEx?

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Jan 13, 2018

@ko80 I cannot reproduce your problem. I am using current Go tip. I changed Go network library a little (to add some debugging), like:

diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go
index 187908b..c4526db 100644
--- a/src/internal/poll/fd_windows.go
+++ b/src/internal/poll/fd_windows.go
@@ -240,6 +240,7 @@ func (s *ioSrv) ExecIO(o *operation, submit func(o *operation) error) (int, erro
 	// Cancel our request.
 	if canCancelIO {
 		err := syscall.CancelIoEx(fd.Sysfd, &o.o)
+		println("ALEX: ", err)
 		// 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.
@@ -247,7 +248,8 @@ func (s *ioSrv) ExecIO(o *operation, submit func(o *operation) error) (int, erro
 		}
 	} else {
 		s.req <- ioSrvReq{o, nil}
-		<-o.errc
+		err3 := <-o.errc
+		println("ALEX2: ", err3)
 	}
 	// Wait for cancelation to complete.
 	fd.pd.waitCanceled(int(o.mode))

and I see this output

Listener started
ALEX2:  (0x0,0x0)
accept tcp 0.0.0.0:8888: i/o timeout
Listener closed
Exit

What do you see, if you make similar changes?

Thank you.

Alex

@ko80

This comment has been minimized.

Copy link
Author

commented Jan 13, 2018

@alexbrainman On Windows XP SP3 I see this:

Listener started
ALEX2:  (0x0,0x0)
Exit

However, on Windows 7 the app outputs this:

Listener started
ALEX2:  (0x0,0x0)
accept tcp 0.0.0.0:8888: i/o timeout
Listener closed
Exit

Thank you for your efforts to fix the issue. If it would be helpful, I can give you private access to a virtual machine running my Windows XP SP3 with Go 1.9.2 installed.

@ko80

This comment has been minimized.

Copy link
Author

commented Jan 13, 2018

@alexbrainman I've just checked the app with your patch on another installations of Windows XP SP3 and Windows XP SP2. In both cases it outputs this:

Listener started
ALEX2:  (0x0,0x0)
accept tcp 0.0.0.0:8888: i/o timeout
Listener closed
Exit

Obviously, this means my XP works in a different way. Unfortunately, I have no ideas what is wrong.

I think, the issue should be closed as it is a failure on my particular installation of Windows XP SP3.

Thanks to all for your time!

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Jan 14, 2018

On Windows XP SP3 I see this:

Listener started
ALEX2: (0x0,0x0)
Exit

That means syscall.CancelIIO call suceeded. But it looks like it did nothing - strange.

However, on Windows 7 the app outputs this:

Listener started
ALEX2: (0x0,0x0)
accept tcp 0.0.0.0:8888: i/o timeout
Listener closed
Exit

This looks strange, the only way this can happen is for canCancelIO to be false. That means you don't have CancelIoEx function on Windows 7 - which is unheard of. Can you add more 'println in fd_windows.go and print the error that syscall.LoadCancelIoEx() call return?

I can give you private access to a virtual machine running my Windows XP SP3 with Go 1.9.2 installed.

Cool, but that is not needed at this stage. I think you can debug things yourself just fine.

I've just checked the app with your patch on another installations of Windows XP SP3 and Windows XP SP2. In both cases it outputs this:

That looks exactly what I see here.

Obviously, this means my XP works in a different way. Unfortunately, I have no ideas what is wrong.

I am bit puzzled too.

I think, the issue should be closed as it is a failure on my particular installation of Windows XP SP3.

Feel free to close the issue, if you like.

Alex

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jun 27, 2018

Closing per earlier comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.