Merge pull request #43 from simonferquel/deadlock-on-concurrent-rw
Flush outgoing content before sending EOF message
diff --git a/file.go b/file.go
index 8c15e41..231863c 100644
--- a/file.go
+++ b/file.go
@@ -219,3 +219,7 @@
f.writeDeadline = t
return nil
}
+
+func (f *win32File) Flush() error {
+ return syscall.FlushFileBuffers(f.handle)
+}
diff --git a/pipe.go b/pipe.go
index b85b2ee..e1b0258 100644
--- a/pipe.go
+++ b/pipe.go
@@ -87,7 +87,11 @@
if f.writeClosed {
return errPipeWriteClosed
}
- _, err := f.win32File.Write(nil)
+ err := f.win32File.Flush()
+ if err != nil {
+ return err
+ }
+ _, err = f.win32File.Write(nil)
if err != nil {
return err
}
diff --git a/pipe_test.go b/pipe_test.go
index 49dad98..2a75302 100644
--- a/pipe_test.go
+++ b/pipe_test.go
@@ -260,3 +260,68 @@
t.Fatalf("expected ErrTimeout, got %v", err)
}
}
+
+type CloseWriter interface {
+ CloseWrite() error
+}
+
+func TestEchoWithMessaging(t *testing.T) {
+ c := PipeConfig{
+ MessageMode: true, // Use message mode so that CloseWrite() is supported
+ InputBufferSize: 65536, // Use 64KB buffers to improve performance
+ OutputBufferSize: 65536,
+ }
+ l, err := ListenPipe(testPipeName, &c)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer l.Close()
+ listenerDone := make(chan bool)
+ clientDone := make(chan bool)
+ go func() {
+ // server echo
+ conn, e := l.Accept()
+ if e != nil {
+ t.Fatal(e)
+ }
+ time.Sleep(500 * time.Millisecond) // make *sure* we don't begin to read before eof signal is sent
+ io.Copy(conn, conn)
+ conn.(CloseWriter).CloseWrite()
+ close(listenerDone)
+ }()
+ timeout := 1 * time.Second
+ client, err := DialPipe(testPipeName, &timeout)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer client.Close()
+
+ go func() {
+ // client read back
+ bytes := make([]byte, 2)
+ n, e := client.Read(bytes)
+ if e != nil {
+ t.Fatal(e)
+ }
+ if n != 2 {
+ t.Fatalf("expected 2 bytes, got %v", n)
+ }
+ close(clientDone)
+ }()
+
+ payload := make([]byte, 2)
+ payload[0] = 0
+ payload[1] = 1
+
+ n, err := client.Write(payload)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 2 {
+ t.Fatalf("expected 2 bytes, got %v", n)
+ }
+ client.(CloseWriter).CloseWrite()
+ <-listenerDone
+ <-clientDone
+}