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
Closed
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Milestone

Comments

@ko80
Copy link

ko80 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
Copy link
Member

ALTree commented Jan 8, 2018

cc @alexbrainman

@ALTree ALTree added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows labels Jan 8, 2018
@ko80
Copy link
Author

ko80 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
Copy link
Contributor

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
Copy link
Member

@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
Copy link
Author

ko80 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
Copy link
Author

ko80 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
Copy link
Member

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
Copy link
Contributor

Closing per earlier comments.

@golang golang locked and limited conversation to collaborators Jun 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

5 participants