Subject: | send_slow needs error checking |
A couple of times I've run into a situation where send_slow is called
on a dropped connection, and huge (gigabytes) of warnings are generated
as a result. Here is the lines of code that produce warnings:
print $self $char; ###
print STDERR "Printed character \'"._make_readable($char)."\' to
${*$self}{exp_Pty_Handle}.\r\n" if ${*$self}{"exp_Debug"} > 1;
# I think I can get away with this if I save it in accum
if (${*$self}{"exp_Log_Stdout"} ||${*$self}{exp_Log_Group}) {
$rmask = "";
vec($rmask,$self->fileno(),1) = 1; ###
# .01 sec granularity should work. If we miss something it will
# probably get flushed later, maybe in an expect call.
while (select($rmask,undef,undef,.01)) {
my $ret = sysread($self,${*$self}{exp_Pty_Buffer},1024); ###
The ### above show where warnings are printed, however the sysread line
in some cases repeats for millions of times. Here is a sample output
from a script using Expect 1.18:
print() on closed filehandle GEN4 at
/volume/perl/lib/site_perl/5.8.5/Expect.pm line 1265.
Use of uninitialized value in vec at
/volume/perl/lib/site_perl/5.8.5/Expect.pm line 1270.
sysread() on closed filehandle GEN4 at
/volume/perl/lib/site_perl/5.8.5/Expect.pm line 1274.
The last message is repeated over 5 million times, and finaly
I get: Out of memory during "large" request for 268439552 bytes, total
sbrk() is 142675968 bytes at /volume/perl/lib/site_perl/5.8.5/Expect.pm
line 1278.
The above line numbers refer to Expect 1.18 but I've seen this with
version 1.15 too, so I assume it affects all versions.
I believe send_slow needs to have a check added, to makes sure
that $self->fileno() is defined. You have similar checks for
$self->fileno() in other parts of the code, so I think you should add
one to the send_slow routine, to avoid letting it go through that
sysread loop milions of times.
I would probably add something like:
my $fileno = $self->fileno(); before calling vec, check $fileno for
definedness, and only if it's defined, move forward (and use $fileno in
the vec() call since you already have it stored).
I will leave to you the details of any error messages, at which precise
point to perform the check, or how to deal with the error, but please
don't proceed into the sysread without making sure $self->fileno() is
defined.
Thanks,
Alex