Skip Menu |

This queue is for tickets about the Mail-GPG CPAN distribution.

Report information
The Basics
Id: 46357
Status: new
Priority: 0/
Queue: Mail-GPG

People
Owner: Nobody in particular
Requestors: hcmav6c02 [...] sneakemail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Mail::GPG blocks in perform_multiplexed_gpg_io at eof($stderr_fh) check
Date: 25 May 2009 17:35:33 -0000
To: bug-Mail-GPG [...] rt.cpan.org
From: hcmav6c02 [...] sneakemail.com
Perl version is 5.10.0 and this is on NetBSD 4.0. Module version is latest: # $Id: GPG.pm,v 1.23 2006/11/18 08:49:05 joern Exp $ $VERSION = "1.0.6"; Mail::GPG is blocking in the above function and I have included a debugged version of the function below (which includes the output I experience when the stall happens). Note that also in another run of the code, I get a stall in the very first outer iteration. The results don't seem to be consistent. Is it possible that the tests in the return statement are overkill? Is there a logic possible that would cause a stall? What would cause eof() itself to block? It seems that eof() isn't called twice on the same filehandle. inner iteration 811 inner iteration 812 exited inner alpha beta charlie delta binary 0, 1 [stalls here -- before printing "binary 1"] [also note the debugged code in another run stalls at the same point but at the second master (outer) iteration] Practically speaking, this means that Mail::GPG is at present unusable to me. I would be happy to provide further details to debug. I hope this information will be helpful. What I see on the host is that the "gpg" process continues to be "running" (although it's not using any CPU). When I replaced "gpg" with a script that does something like ``real-gpg "$@" > file; exec cat file'', then the cat process itself just hangs around there too. There seems to be a logic error (perhaps overkill) in the checking of the return condition. The data is processed fine, it seems, since there are several hundred successful iterations of the loop above it. But the clues I get on the tail output suggest that gpg has done what it needs to do, and perhaps shouldn't need to go through another outer iteration. Maybe in the earlier iteration, when $status_fh has been found to be undef, then that alone could mean that there can be no more practical processing that can take place. sub perform_multiplexed_gpg_io { my $self = shift; my %par = @_; my ($data_fh, $data_canonify, $stdin_fh, $stderr_fh) = @par{'data_fh','data_canonify','stdin_fh','stderr_fh'}; my ($stdout_fh, $status_fh, $stderr_sref, $stdout_sref) = @par{'stdout_fh','status_fh','stderr_sref','stdout_sref'}; my ($status_sref) = $par{'status_sref'}; print STDERR "one\n"; #-- perl < 5.6 compatibility: seek() and read() work #-- on native GLOB filehandle only, so dertmine type #-- of filehandle here my $data_fh_glob = ref $data_fh eq 'GLOB'; #-- rewind the data filehandle if ($data_fh_glob) { seek $data_fh, 0, 0; } else { $data_fh->seek( 0, 0 ); } print STDERR "two\n"; #-- create IO::Select objects for all #-- filehandles in question my $stdin = IO::Select->new($stdin_fh); my $stderr = IO::Select->new($stderr_fh); my $stdout = IO::Select->new($stdout_fh); my $status = $status_fh ? IO::Select->new($status_fh) : undef; my $buffer; print STDERR "just before while loop\n"; my $myiter =0 ; while (1) { $myiter++;print STDERR "iteration $myiter\n"; my $myiter2=0; #-- as long we has data try to write #-- it into gpg while ( $data_fh && $stdin->can_write(0.1) ) { $myiter2++;print STDERR "inner iteration $myiter2\n"; if ( $data_fh_glob ? read $data_fh, $buffer, 1024 : $data_fh->read( $buffer, 1024 ) ) { #-- ok, got a block of data if ($data_canonify) { #-- canonify it if requested $buffer =~ s/\x0A/\x0D\x0A/g; $buffer =~ s/\x0D\x0D\x0A/\x0D\x0A/g; } #-- feed it into gpg print $stdin_fh $buffer; } else { #-- no data read, close gpg's stdin #-- and set the data filehandle to false close $stdin_fh; $data_fh = 0; } } print STDERR "exited inner\n"; print STDERR "alpha\n"; #-- probably we can read from gpg's stdout while ( $stdout->can_read(0.1) ) { last if eof($stdout_fh); $$stdout_sref .= <$stdout_fh>; } print STDERR "beta\n"; #-- probably we can read from gpg's stderr while ( $stderr->can_read(0.1) ) { last if eof($stderr_fh); $$stderr_sref .= <$stderr_fh>; } print STDERR "charlie\n"; #-- probably we can read from gpg's status if ($status) { while ( $status->can_read(0.1) ) { last if eof($status_fh); $$status_sref .= <$status_fh>; } } print STDERR "delta\n"; #-- we're finished if no more data left #-- and both gpg's stdout and stderr #-- are at eof. print STDERR "binary 0, ", !$data_fh, "\n"; print STDERR "binary 1, ", eof($stderr_fh), "\n"; print STDERR "binary 2, ", eof($stdout_fh), "\n"; print STDERR "binary 3, ", !$status_fh, "\n"; if ($status_fh) { print STDERR "binary 4, ", eof($status_fh), "\n"; } else { print STDERR "binary 4 - check skipped due to undeflike quality of status_fh.\n"; } return if !$data_fh && eof($stderr_fh) && eof($stdout_fh) && ( !$status_fh || eof($status_fh) ); print STDERR "echo\n"; } #.... #exited inner #alpha #beta #charlie #delta #binary 0, 1 #binary 1, #binary 2, #binary 3, 1 #binary 4 - check skipped due to undeflike quality of status_fh. #echo #iteration 2 #exited inner #alpha #beta #charlie #delta #binary 0, 1 #[stalls here] 1; }
Subject: Re: [rt.cpan.org #46357] AutoReply: Mail::GPG blocks in perform_multiplexed_gpg_io at eof($stderr_fh) check
Date: 25 May 2009 18:29:18 -0000
To: bug-Mail-GPG [...] rt.cpan.org
From: hcmav6c02 [...] sneakemail.com
It's also stalling at: #-- feed it into gpg print $stdin_fh $buffer; unless I perform the workaround of creating a fake-gpg wrapper script that firstly buffers the input completely, writes it to a file, performs real-gpg on that file and outputs it to a new one, and then finally does "exec cat -u ${OUTPUTFILE}": #!/bin/ksh # fake-gpg if echo "$@" | grep -q -- --sign then if echo "$@" | grep -q -- --encrypt then INPUTFILE="/tmp/output.$RANDOM.$RANDOM" OUTPUTFILE="/tmp/output.$RANDOM.$RANDOM.out" /bin/cat -u > "${INPUTFILE}" sync gpg-real "$@" < "${INPUTFILE}" > "${OUTPUTFILE}" sync exec /bin/cat -u "${OUTPUTFILE}" fi fi exec gpg-real "$@" When I set gpg_call to the real GnuPG executable, then it stalls at the print line that I mentioned, above.