@@ -15,7 +15,6 @@ import (
1515//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
1616//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
1717//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
18- //sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
1918//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
2019//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
2120//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
@@ -139,12 +138,14 @@ func (s pipeAddress) String() string {
139138}
140139
141140// DialPipe connects to a named pipe by path, timing out if the connection
142- // takes longer than the specified duration. If timeout is nil, then the timeout
143- // is the default timeout established by the pipe server.
141+ // takes longer than the specified duration. If timeout is nil, then we use
142+ // a default timeout of 5 seconds. (We do not use WaitNamedPipe.)
144143func DialPipe (path string , timeout * time.Duration ) (net.Conn , error ) {
145144 var absTimeout time.Time
146145 if timeout != nil {
147146 absTimeout = time .Now ().Add (* timeout )
147+ } else {
148+ absTimeout = time .Now ().Add (time .Second * 2 )
148149 }
149150 var err error
150151 var h syscall.Handle
@@ -153,22 +154,13 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
153154 if err != cERROR_PIPE_BUSY {
154155 break
155156 }
156- now := time .Now ()
157- var ms uint32
158- if absTimeout .IsZero () {
159- ms = cNMPWAIT_USE_DEFAULT_WAIT
160- } else if now .After (absTimeout ) {
161- ms = cNMPWAIT_NOWAIT
162- } else {
163- ms = uint32 (absTimeout .Sub (now ).Nanoseconds () / 1000 / 1000 )
164- }
165- err = waitNamedPipe (path , ms )
166- if err != nil {
167- if err == cERROR_SEM_TIMEOUT {
168- return nil , ErrTimeout
169- }
170- break
157+ if time .Now ().After (absTimeout ) {
158+ return nil , ErrTimeout
171159 }
160+
161+ // Wait 10 msec and try again. This is a rather simplistic
162+ // view, as we always try each 10 milliseconds.
163+ time .Sleep (time .Millisecond * 10 )
172164 }
173165 if err != nil {
174166 return nil , & os.PathError {Op : "open" , Path : path , Err : err }
@@ -349,13 +341,23 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
349341 if err != nil {
350342 return nil , err
351343 }
352- // Immediately open and then close a client handle so that the named pipe is
353- // created but not currently accepting connections.
344+ // Create a client handle and connect it. This results in the pipe
345+ // instance always existing, so that clients see ERROR_PIPE_BUSY
346+ // rather than ERROR_FILE_NOT_FOUND. This ties the first instance
347+ // up so that no other instances can be used. This would have been
348+ // cleaner if the Win32 API matched CreateFile with ConnectNamedPipe
349+ // instead of CreateNamedPipe. (Apparently created named pipes are
350+ // considered to be in listening state regardless of whether any
351+ // active calls to ConnectNamedPipe are outstanding.)
354352 h2 , err := createFile (path , 0 , 0 , nil , syscall .OPEN_EXISTING , cSECURITY_SQOS_PRESENT | cSECURITY_ANONYMOUS , 0 )
355353 if err != nil {
356354 syscall .Close (h )
357355 return nil , err
358356 }
357+ // Close the client handle. The server side of the instance will
358+ // still be busy, leading to ERROR_PIPE_BUSY instead of
359+ // ERROR_NOT_FOUND, as long as we don't close the server handle,
360+ // or disconnect the client with DisconnectNamedPipe.
359361 syscall .Close (h2 )
360362 l := & win32PipeListener {
361363 firstHandle : h ,
0 commit comments