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

The first *win32PipeListener.Accept will cause the client hanged in Windows 7 #173

Open
mi1eschen opened this issue Jun 10, 2020 · 2 comments

Comments

@mi1eschen
Copy link

I was trying go-winio in my project, but I noticed that the same code had different results in Win 7 and Win 10. In Win 7, the client was hanged on first connecting after server restarted, and worked correctly after the second time. After debugged and found that server's syscall.getQueuedCompletionStatus couldn't be triggered when the client first connected. Then I tried to find the reason and noticed that win32PipeListener.firstHandle's access was syscall.SYNCHRONIZE. I found they created named pipe with full access in the loop in this example, so I tried to modify code and the bellow is the diff block.

diff --git a/pipe.go b/pipe.go                                                                      
index d6a46f6..ac59ca0 100644                                                                       
--- a/pipe.go                                                                                       
+++ b/pipe.go                                                                                       
@@ -259,6 +259,7 @@ type acceptResponse struct {                                                    
                                                                                                    
 type win32PipeListener struct {                                                                    
        firstHandle syscall.Handle                                                                  
+       handle      syscall.Handle                                                                  
        path        string                                                                          
        config      PipeConfig                                                                      
        acceptCh    chan (chan acceptResponse)                                                      
@@ -319,7 +320,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
                // By not asking for read or write access, the named pipe file system               
                // will put this pipe into an initially disconnected state, blocking                
                // client connections until the next call with first == false.                      
-               access = syscall.SYNCHRONIZE                                                        
+               // access = syscall.SYNCHRONIZE                                                     
        }                                                                                           
                                                                                                    
        timeout := int64(-50 * 10000) // 50ms
@@ -338,13 +339,19 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
 }                                                                                                    
                                                                                                      
 func (l *win32PipeListener) makeServerPipe() (*win32File, error) {                                   
-       h, err := makeServerPipeHandle(l.path, nil, &l.config, false)                                 
-       if err != nil {                                                                               
-               return nil, err                                                                       
+       handle := l.handle                                                                            
+       if handle == 0 {                                                                              
+               h, err := makeServerPipeHandle(l.path, nil, &l.config, false)                         
+               if err != nil {                                                                       
+                       return nil, err                                                               
+               }                                                                                     
+               handle = h                                                                            
+       } else {                                                                                      
+               l.handle = 0                                                                          
        }                                                                                             
-       f, err := makeWin32File(h)                                                                    
+       f, err := makeWin32File(handle)                                                               
        if err != nil {                                                                               
-               syscall.Close(h)                                                                      
+               syscall.Close(handle)                                                                 
                return nil, err                                                                       
        }                                                                                             
        return f, nil                                                                                 
@@ -451,6 +458,7 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {               
        }                                                                                             
        l := &win32PipeListener{                                                                      
                firstHandle: h,                                                                       
+               handle:      h,                                                                       
                path:        path,                                                                    
                config:      *c,                                                                      
                acceptCh:    make(chan (chan acceptResponse)),                                        

Then it worked on both Win 7 and Win 10!

Here is my test code. link

Actually, I think the current implementation is correct, and I still don't know why it fails on Win 7.

Sorry for poor English...

Test Environment:
OS: Windows 7 ( 7601: service pack 1 )

Build Environment:
OS: Windows 10 (1909)
GO version: 1.14 windows/amd64

@gps949
Copy link

gps949 commented May 6, 2023

I saw 0.6.1 was leased. But this issue still open. So this one would be "won't fix" due to Windows 7 is out of support?

@tandem97
Copy link

I have the same problem. It is critical problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants