Merge pull request #4 from hanwen/master

Make Listen exclusive for a given named pipe.
diff --git a/npipe_windows.go b/npipe_windows.go
index a70a03c..bcff920 100644
--- a/npipe_windows.go
+++ b/npipe_windows.go
@@ -254,7 +254,7 @@
 //
 // Listen will return a PipeError for an incorrectly formatted pipe name.
 func Listen(address string) (*PipeListener, error) {
-	handle, err := createPipe(address)
+	handle, err := createPipe(address, true)
 	if err == error_invalid_name {
 		return nil, badAddr(address)
 	}
@@ -295,7 +295,7 @@
 	handle := l.handle
 	if handle == 0 {
 		var err error
-		handle, err = createPipe(string(l.addr))
+		handle, err = createPipe(string(l.addr), false)
 		if err != nil {
 			return nil, err
 		}
@@ -459,16 +459,21 @@
 	return string(a)
 }
 
-// createPipe is a helper function to make sure we always create pipes with the same arguments,
-// since subsequent calls to create pipe need to use the same arguments as the first one.
-func createPipe(address string) (syscall.Handle, error) {
+// createPipe is a helper function to make sure we always create pipes
+// with the same arguments, since subsequent calls to create pipe need
+// to use the same arguments as the first one. If first is set, fail
+// if the pipe already exists.
+func createPipe(address string, first bool) (syscall.Handle, error) {
 	n, err := syscall.UTF16PtrFromString(address)
 	if err != nil {
 		return 0, err
 	}
-
+	mode := uint32(pipe_access_duplex | syscall.FILE_FLAG_OVERLAPPED)
+	if first {
+		mode |= file_flag_first_pipe_instance
+	}
 	return createNamedPipe(n,
-		pipe_access_duplex|syscall.FILE_FLAG_OVERLAPPED,
+		mode,
 		pipe_type_byte,
 		pipe_unlimited_instances,
 		512, 512, 0, nil)
diff --git a/npipe_windows_test.go b/npipe_windows_test.go
index d8f5df7..3aadf95 100644
--- a/npipe_windows_test.go
+++ b/npipe_windows_test.go
@@ -77,6 +77,22 @@
 	}
 }
 
+// TestDoubleListen makes sure we can't listen to the same address twice.
+func TestDoubleListen(t *testing.T) {
+	address := `\\.\pipe\TestDoubleListen`
+	ln1, err := Listen(address)
+	if err != nil {
+		t.Fatalf("Listen(%q): %v", address, err)
+	}
+	defer ln1.Close()
+
+	ln2, err := Listen(address)
+	if err == nil {
+		ln2.Close()
+		t.Fatalf("second Listen on %q succeeded.", address)
+	}
+}
+
 // Test that PipeConn's read deadline works correctly
 func TestReadDeadline(t *testing.T) {
 	address := `\\.\pipe\TestReadDeadline`
@@ -333,6 +349,13 @@
 // and then dial into it with several clients in succession
 func TestCommonUseCase(t *testing.T) {
 	addrs := []string{`\\.\pipe\TestCommonUseCase`, `\\127.0.0.1\pipe\TestCommonUseCase`}
+	// always listen on the . version, since IP won't work for listening
+	ln, err := Listen(addrs[0])
+	if err != nil {
+		t.Fatalf("Listen(%q) failed: %v", addrs[0], err)
+	}
+	defer ln.Close()
+
 	for _, address := range addrs {
 		convos := 5
 		clients := 10
@@ -342,12 +365,6 @@
 
 		go aggregateDones(done, quit, clients)
 
-		// always listen on the . version, since IP won't work for listening
-		ln, err := Listen(addrs[0])
-		if err != nil {
-			t.Fatal("Error starting to listen on pipe: ", err)
-		}
-
 		for x := 0; x < clients; x++ {
 			go startClient(address, done, convos, t)
 		}