Subject: | Win32::Pipe fails to disconnect "server" pipes (fix included) |
Date: | Thu, 25 Oct 2012 13:26:39 -0400 |
To: | bug-libwin32 [...] rt.cpan.org |
From: | Javier Fernandez <jfernand [...] mtu.edu> |
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)));