For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > April 2004 > strange side-effect (bug?) in Net::SMTP









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author strange side-effect (bug?) in Net::SMTP
Ian D.

2004-04-15, 12:34 pm

This is perl, version 5.005_02 built for sun4-solaris

I have an array that is wiped out when calling Net::SMTP->new. Here
is a debug from it. Note my array is intact at line 356, but after a
'next', it is gone:

main::check_mailservers(./conchk:356):
356: $smtp = Net::SMTP->new('ondar',Timeout=>10,Debug=>0);
DB<2> x @MAILSERVERS
0 ARRAY(0x6ea244)
0 'sendmail'
1 'ondar'
2 'nobody@cablelabs.com'
3 'nobody@localhost'
4 150
DB<3> n

main::check_mailservers(./conchk:357):
357: $td=tv_interval($t0);
DB<3> x @MAILSERVERS
0 undef <======= WHAT THE HECK JUST HAPPENED???

A bug?

Ian
Bob Walton

2004-04-15, 11:30 pm

Ian D. wrote:

> This is perl, version 5.005_02 built for sun4-solaris
>
> I have an array that is wiped out when calling Net::SMTP->new. Here
> is a debug from it. Note my array is intact at line 356, but after a
> 'next', it is gone:
>
> main::check_mailservers(./conchk:356):
> 356: $smtp = Net::SMTP->new('ondar',Timeout=>10,Debug=>0);
> DB<2> x @MAILSERVERS
> 0 ARRAY(0x6ea244)
> 0 'sendmail'
> 1 'ondar'
> 2 'nobody@cablelabs.com'
> 3 'nobody@localhost'
> 4 150



So, @MAILSERVERS is a one-element array, the value of which is a
reference to another array with 5 elements. The first four of those
elements have values which are various strings, and the fifth has a
value which is an integer.


> DB<3> n
>
> main::check_mailservers(./conchk:357):
> 357: $td=tv_interval($t0);
> DB<3> x @MAILSERVERS
> 0 undef <======= WHAT THE HECK JUST HAPPENED???



And now @MAILSERVERS is still a one-element array, but the value of it
is now undef, rather than an array reference. This behavior could be
explained if junk450.pl is the following program:

D:\junk>type junk450.pl
$MAILSERVERS[0]=[
'sendmail',
'ondar',
'nobody@cablelabs.com',
'nobody@localhost',
150,
];
for $smtp (@MAILSERVERS){
$smtp=undef;
}
--------------------------------
and it is stepped through as follows:
--------------------------------

D:\junk>perl -d junk450.pl

Loading DB routines from perl5db.pl version 1.19
Editor support available.

Enter h or `h h' for help, or `perldoc perldebug' for more help.

main::(junk450.pl:1): $MAILSERVERS[0]=[
main::(junk450.pl:2): 'sendmail',
main::(junk450.pl:3): 'ondar',
main::(junk450.pl:4): 'nobody@cablelabs.com',
main::(junk450.pl:5): 'nobody@localhost',
main::(junk450.pl:6): 150,
main::(junk450.pl:7): ];
DB<1> s
main::(junk450.pl:8): for $smtp (@MAILSERVERS){
DB<1> s
main::(junk450.pl:9): $smtp=undef;
DB<1> x @MAILSERVERS
0 ARRAY(0x1558798)
0 'sendmail'
1 'ondar'
2 'nobody@cablelabs.com'
3 'nobody@localhost'
4 150
DB<2> n
main::(junk450.pl:8): for $smtp (@MAILSERVERS){
DB<2> x @MAILSERVERS
0 undef
DB<3>


Note the debug output which is identical to yours (except of course for
the address of the anonymous array and the line numbers).


>
> A bug?



Yes, in your code.


>
> Ian
>


--
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl

Ian D.

2004-04-16, 10:32 am

Bob Walton <invalid-email@rochester.rr.com> wrote in message news:<407F462E.6050803@rochester.rr.com>...[color=darkred]
> Ian D. wrote:
>
>
>
> So, @MAILSERVERS is a one-element array, the value of which is a
> reference to another array with 5 elements. The first four of those
> elements have values which are various strings, and the fifth has a
> value which is an integer.
>
>
>
>
> And now @MAILSERVERS is still a one-element array, but the value of it
> is now undef, rather than an array reference. This behavior could be
> explained if junk450.pl is the following program:
>
> D:\junk>type junk450.pl
> $MAILSERVERS[0]=[
> 'sendmail',
> 'ondar',
> 'nobody@cablelabs.com',
> 'nobody@localhost',
> 150,
> ];
> for $smtp (@MAILSERVERS){
> $smtp=undef;
> }
> --------------------------------
> and it is stepped through as follows:
> --------------------------------
>
> D:\junk>perl -d junk450.pl
>
> Loading DB routines from perl5db.pl version 1.19
> Editor support available.
>
> Enter h or `h h' for help, or `perldoc perldebug' for more help.
>
> main::(junk450.pl:1): $MAILSERVERS[0]=[
> main::(junk450.pl:2): 'sendmail',
> main::(junk450.pl:3): 'ondar',
> main::(junk450.pl:4): 'nobody@cablelabs.com',
> main::(junk450.pl:5): 'nobody@localhost',
> main::(junk450.pl:6): 150,
> main::(junk450.pl:7): ];
> DB<1> s
> main::(junk450.pl:8): for $smtp (@MAILSERVERS){
> DB<1> s
> main::(junk450.pl:9): $smtp=undef;
> DB<1> x @MAILSERVERS
> 0 ARRAY(0x1558798)
> 0 'sendmail'
> 1 'ondar'
> 2 'nobody@cablelabs.com'
> 3 'nobody@localhost'
> 4 150
> DB<2> n
> main::(junk450.pl:8): for $smtp (@MAILSERVERS){
> DB<2> x @MAILSERVERS
> 0 undef
> DB<3>
>
>
> Note the debug output which is identical to yours (except of course for
> the address of the anonymous array and the line numbers).
>
>
>
>
> Yes, in your code.
>
>


Thanks for the reply, but I don't think that is it. I don't have to
assign the new Net::SMTP object to anything, and my array is still
wiped out. Here's more debug output:

DB<7> x @MAILSERVERS
0 ARRAY(0x740594)
0 'sendmail'
1 'ondar'
2 'nobody@cablelabs.com'
3 'nobody@localhost'
4 150
DB<8> Net::SMTP->new('ondar');
DB<9> x @MAILSERVERS
0 undef


Somehow my anonymous array at 0x740594 in this case is being
overwritten in the new() function, but I don't know why.

Ian
James Willmore

2004-04-16, 10:32 am

On Fri, 16 Apr 2004 06:30:23 -0700, Ian D. wrote:

[ ... ]

> DB<7> x @MAILSERVERS
> 0 ARRAY(0x740594)
> 0 'sendmail'
> 1 'ondar'
> 2 'nobody@cablelabs.com'
> 3 'nobody@localhost'
> 4 150
> DB<8> Net::SMTP->new('ondar');
> DB<9> x @MAILSERVERS
> 0 undef
>
>
> Somehow my anonymous array at 0x740594 in this case is being
> overwritten in the new() function, but I don't know why.


Can you provide the offending code (**NOT** the whole script, just the
portions that appear to be given you issue). I can see something is going
South, but at a loss to know why.

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
I've given up reading books; I find it takes my mind off myself.


Ian D.

2004-04-16, 2:33 pm

Bob Walton <invalid-email@rochester.rr.com> wrote in message news:<407F462E.6050803@rochester.rr.com>...[color=darkred]
> Ian D. wrote:
>
>
>
> So, @MAILSERVERS is a one-element array, the value of which is a
> reference to another array with 5 elements. The first four of those
> elements have values which are various strings, and the fifth has a
> value which is an integer.
>
>
>
>
> And now @MAILSERVERS is still a one-element array, but the value of it
> is now undef, rather than an array reference. This behavior could be
> explained if junk450.pl is the following program:
>
> D:\junk>type junk450.pl
> $MAILSERVERS[0]=[
> 'sendmail',
> 'ondar',
> 'nobody@cablelabs.com',
> 'nobody@localhost',
> 150,
> ];
> for $smtp (@MAILSERVERS){
> $smtp=undef;
> }
> --------------------------------
> and it is stepped through as follows:
> --------------------------------
>
> D:\junk>perl -d junk450.pl
>
> Loading DB routines from perl5db.pl version 1.19
> Editor support available.
>
> Enter h or `h h' for help, or `perldoc perldebug' for more help.
>
> main::(junk450.pl:1): $MAILSERVERS[0]=[
> main::(junk450.pl:2): 'sendmail',
> main::(junk450.pl:3): 'ondar',
> main::(junk450.pl:4): 'nobody@cablelabs.com',
> main::(junk450.pl:5): 'nobody@localhost',
> main::(junk450.pl:6): 150,
> main::(junk450.pl:7): ];
> DB<1> s
> main::(junk450.pl:8): for $smtp (@MAILSERVERS){
> DB<1> s
> main::(junk450.pl:9): $smtp=undef;
> DB<1> x @MAILSERVERS
> 0 ARRAY(0x1558798)
> 0 'sendmail'
> 1 'ondar'
> 2 'nobody@cablelabs.com'
> 3 'nobody@localhost'
> 4 150
> DB<2> n
> main::(junk450.pl:8): for $smtp (@MAILSERVERS){
> DB<2> x @MAILSERVERS
> 0 undef
> DB<3>
>
>
> Note the debug output which is identical to yours (except of course for
> the address of the anonymous array and the line numbers).
>
>
>
>
> Yes, in your code.
>
>


Well, it looks like new() is modifying $_. I use $_ as my control
variable in a foreach loop (implicitly), each time it points to an
element of @MAILSERVERS. Net::SMTP->new() seems to change $_, and
hence changes my array.

main::check_mailservers(./conchk:357):
357: Net::SMTP->new('ondar');
DB<11> x \$_
0 SCALAR(0x79cac8)
-> ARRAY(0x79ca98)
0 'sendmail'
1 'ondar'
2 'nobody@cablelabs.com'
3 'nobody@localhost'
4 150
DB<12> n

main::check_mailservers(./conchk:358):
358: $td=tv_interval($t0);
DB<12> x \$_
0 SCALAR(0x79cac8)
-> undef


If I use another variable to drive my loop, all is well. I don't
believe a subroutine should be modifying $_, should it?

Ian
Bob Walton

2004-04-16, 9:31 pm

Ian D. wrote:

> Bob Walton <invalid-email@rochester.rr.com> wrote in message news:<407F462E.6050803@rochester.rr.com>...
>


....

[color=darkred]
> If I use another variable to drive my loop, all is well. I don't
> believe a subroutine should be modifying $_, should it?
>
> Ian
>



As for whether a sub can modify $_, that is easily tested:

D:\junk>type junk450b.pl
$_='something';
sub1();
print "\$_ is now $_\n";

sub sub1{
$_='something else';
}

D:\junk>perl junk450b.pl
$_ is now something else

D:\junk>

And the answer is: Yes, a sub can modify $_. $_, along with all other
"punctuation" variables, is a true global -- if modified somewhere, it
is modified everywhere. A *good* *nice* sub would avoid using $_, or if
it does use it, would preserve the value of $_ and any other globals it
might change, through the use of local(). But how many folks actually
take the time and energy to do that in their subs (or even know they
should)? And how easy is it to mess up? Better to never count on $_
being preserved over a call. But nonetheless, a good module *should*
preserve globals. So I probably owe you an apology -- the bug probably
was in Net::SMTP. But it is still counting on a lot to assume that all
the stuff involved with a complicated module will actually preserve $_,
and it is still better to not count on it. What if the module takes an
execution path the testing didn't test, for example?


Hmmmmmmmm...a test program on my system does not duplicate your
behavior. Your Perl is pretty ancient (5.005_02) -- you might try a
modern version and see if the problem has been fixed. Here is a test
program almost identical to what you posted and its output:

D:\junk>type junk450a.pl
use Net::SMTP;
use Data::Dumper;
$MAILSERVERS[0]=[
'sendmail',
'ondar',
'nobody@cablelabs.com',
'nobody@localhost',
150,
];
foreach (@MAILSERVERS) {
my($type,$server,$from,$to,$defer,$black
out)=@$_;
$statfile=$MAILSERVER_STATE . $server;
print "Connecting to $type server $server...";
$t0=[gettimeofday];
# $failed=do_smtp($server,$from,$to);
#$smtp = Net::SMTP->new('ondar');
Net::SMTP->new('ondar');
print Dumper(@MAILSERVERS);
# @MAILSERVERS is gone now
# $td=tv_interval($t0); #commented because undefined
}

D:\junk>perl junk450a.pl
Connecting to sendmail server ondar...$VAR1 = [
'sendmail',
'ondar',
'nobody@cablelabs.com',
'nobody@localhost',
150
];

D:\junk>ver

Windows 98 [Version 4.10.2222]


D:\junk>perl -v

This is perl, v5.8.0 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2002, Larry Wall

Binary build 806 provided by ActiveState Corp. http://www.ActiveState.com
Built 00:45:44 Mar 31 2003

--
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl

Ian D.

2004-04-19, 10:38 am

Bob Walton <invalid-email@rochester.rr.com> wrote in message news:<40807AD5.8020803@rochester.rr.com>...
> Ian D. wrote:
>
>
>
> ...
>
>
>
>
> As for whether a sub can modify $_, that is easily tested:
>
> D:\junk>type junk450b.pl
> $_='something';
> sub1();
> print "\$_ is now $_\n";
>
> sub sub1{
> $_='something else';
> }
>
> D:\junk>perl junk450b.pl
> $_ is now something else
>
> D:\junk>
>
> And the answer is: Yes, a sub can modify $_. $_, along with all other
> "punctuation" variables, is a true global -- if modified somewhere, it
> is modified everywhere. A *good* *nice* sub would avoid using $_, or if
> it does use it, would preserve the value of $_ and any other globals it
> might change, through the use of local(). But how many folks actually
> take the time and energy to do that in their subs (or even know they
> should)? And how easy is it to mess up? Better to never count on $_
> being preserved over a call. But nonetheless, a good module *should*
> preserve globals. So I probably owe you an apology -- the bug probably
> was in Net::SMTP. But it is still counting on a lot to assume that all
> the stuff involved with a complicated module will actually preserve $_,
> and it is still better to not count on it. What if the module takes an
> execution path the testing didn't test, for example?
>
>
> Hmmmmmmmm...a test program on my system does not duplicate your
> behavior. Your Perl is pretty ancient (5.005_02) -- you might try a
> modern version and see if the problem has been fixed. Here is a test
> program almost identical to what you posted and its output:
>
> D:\junk>type junk450a.pl
> use Net::SMTP;
> use Data::Dumper;
> $MAILSERVERS[0]=[
> 'sendmail',
> 'ondar',
> 'nobody@cablelabs.com',
> 'nobody@localhost',
> 150,
> ];
> foreach (@MAILSERVERS) {
> my($type,$server,$from,$to,$defer,$black
out)=@$_;
> $statfile=$MAILSERVER_STATE . $server;
> print "Connecting to $type server $server...";
> $t0=[gettimeofday];
> # $failed=do_smtp($server,$from,$to);
> #$smtp = Net::SMTP->new('ondar');
> Net::SMTP->new('ondar');
> print Dumper(@MAILSERVERS);
> # @MAILSERVERS is gone now
> # $td=tv_interval($t0); #commented because undefined
> }
>
> D:\junk>perl junk450a.pl
> Connecting to sendmail server ondar...$VAR1 = [
> 'sendmail',
> 'ondar',
> 'nobody@cablelabs.com',
> 'nobody@localhost',
> 150
> ];
>
> D:\junk>ver
>
> Windows 98 [Version 4.10.2222]
>
>
> D:\junk>perl -v
>
> This is perl, v5.8.0 built for MSWin32-x86-multi-thread
> (with 1 registered patch, see perl -V for more detail)
>
> Copyright 1987-2002, Larry Wall
>
> Binary build 806 provided by ActiveState Corp. http://www.ActiveState.com
> Built 00:45:44 Mar 31 2003



I agree that you shouldn't count on $_ across function calls, and I
have fixed that. As for the version of perl, I did try my code on a
newer version and did not have the same problem. So I really had 2
ways to fix the problem. The easiest, of course, was to just change
my control variable. Apology accepted. :-)

Ian
James Willmore

2004-04-27, 2:06 am

On Fri, 16 Apr 2004 06:30:23 -0700, Ian D. wrote:

> Thanks for the reply, but I don't think that is it. I don't have to
> assign the new Net::SMTP object to anything, and my array is still
> wiped out. Here's more debug output:
>
> DB<7> x @MAILSERVERS
> 0 ARRAY(0x740594)
> 0 'sendmail'
> 1 'ondar'
> 2 'nobody@cablelabs.com'
> 3 'nobody@localhost'
> 4 150
> DB<8> Net::SMTP->new('ondar');
> DB<9> x @MAILSERVERS
> 0 undef
>
>
> Somehow my anonymous array at 0x740594 in this case is being
> overwritten in the new() function, but I don't know why.


Can you provide the offending code (**NOT** the whole script, just the
portions that appear to be given you issue). I can see something is going
South, but at a loss to know why.

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
I've given up reading books; I find it takes my mind off myself.


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com