[rt.cpan.org #80396] Win32::Pipe fails to disconnect "server" pipes (fix included)

[email protected] ("Javier Fernandez via RT") Thu, 25 Oct 2012 13:26:52 -0400
Newsgroups perl.libwin32
Message-ID <[email protected]>
Thu Oct 25 13:26:52 2012: Request 80396 was acted upon.
Transaction: Ticket created by [email protected]
       Queue: libwin32
     Subject: Win32::Pipe fails to disconnect "server" pipes (fix included)
   Broken in: (no value)
    Severity: (no value)
       Owner: Nobody
  Requestors: [email protected]
      Status: new
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=80396 >


This problem seems to be at least 12 years old (http://code.activestate.com/lists/perl-win32-admin/313/). Do I get an award for oldest module bug found?

There is a bug in the arguments check in the call to Pipe::Disconnect in Pipe.xs which causes pipes to never be disconnected. 

This causes pipe servers which attempt to Disconnect() fail in their second call to Connect().

This is happening on v 0.024 of Win32::Pipe.
----
C:\>perl -v

This is perl 5, version 16, subversion 0 (v5.16.0) built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2012, Larry Wall

Binary build 1600 [295879] provided by ActiveState http://www.ActiveState.com
Built Jun 11 2012 12:43:38

----
Example code:

SERVER:

use Win32::Pipe;
 my $pipe = new Win32::Pipe("work"); 
  while(1) {
    $pipe->Connect() or die 'Connect';
    $pipe->Write('Test') or die "Error:".$pipe->Error();
    $pipe->Disconnect();
  }
}

CLIENT:

use Win32::Pipe;

my $pipe = new Win32::Pipe('\\\\.\\pipe\\work');

print $pipe->Read();
$pipe->Close();

my $pipe = new Win32::Pipe('\\\\.\\pipe\\work');

print $pipe->Read();
$pipe->Close();

The second call to Connect fails
----
Cause:

Line 307 of Pipe.xs reads:

	if(items > 0 && items < 3){
		CROAK("usage: Disconnect($PipeHandle [, $iPurge]);\n");
	}
which CROAKS() when the number of parameters is 1 or 2. The code is intended to accept 1 or 2 parameters, so the logic needs to be reversed, the code never gets to Pipe->Disconnect(iPurge):

	if(items < 1 || items > 2)){
		CROAK("usage: Disconnect($PipeHandle [, $iPurge]);\n");
	}
----
Diff:

bash-3.2# diff -u Pipe.xs.orig Pipe.xs 
--- Pipe.xs.orig	2012-10-23 14:43:57.000000000 -0400
+++ Pipe.xs	2012-10-23 14:44:26.000000000 -0400
@@ -304,7 +304,7 @@
	int		iResult = 0;
	int		iPurge = 0;

-	if(items > 0 && items < 3){
+	if(items < 1 || items > 2)){
		CROAK("usage: Disconnect($PipeHandle [, $iPurge]);\n");
	}
	Pipe = INT2PTR(class CPipe *, SvIV(ST(0)));