How to debug bizarre memory corruption in mod_perl

How to debug bizarre memory corruption in mod_perl

am 08.07.2008 19:23:35 von Stephen Clouse

------=_Part_2726_14093633.1215537815428
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

I will preface this message with this: this is not a mod_perl bug or
problem, but it involves a mod_perl application, so this is probably a good
place to get advice from experienced mod_perl users/developers.

I have an application that ran on mod_perl 1.3 and perl 5.8 for a long time,
that I recently ported over to a Fedora 9 box, thus moving it to mod_perl
2.0 and perl 5.10.

Under this new environment, I am getting some of the most bizarre and
insidious perl core errors I've ever seen in my 15 years of using perl.
Here's a sampling:

Attempt to free unreferenced scalar: SV 0xbd266be4, Perl interpreter:
0xba01c410 at /usr/lib/perl5/vendor_perl/5.10.0/HTML/Mason/Component.pm line
147.
panic: attempt to copy value 20 to a freed scalar bd49dffc
Use of freed value in iteration
panic: free from wrong pool

Not to mention countless application errors involving dereferencing, where
things that are supposed to be arrays and hashrefs have magically turned
into strings and key values, and vice versa.

Now I realize this is not an issue with mod_perl itself. Obviously
something is doing a massive fandango on core and corrupting the Perl
stack/arena over time. Note that running Apache with MaxRequestsPerChild =
1 seems to mitigate the issue, so it's a problem that occurs at runtime.

My problem is that I don't even know where or how to start tracing or
debugging such an issue to determine precisely what is scribbling on perl's
memory. If this was a standalone app, it would be simple enough to run it
through gdb and trace everything out, but in a mod_perl environment....

Any advice on how to proceed is greatly appreciated.

--
Stephen Clouse

------=_Part_2726_14093633.1215537815428
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

I will preface this message with this: this is not a mod_perl bug or problem, but it involves a mod_perl application, so this is probably a good place to get advice from experienced mod_perl users/developers.

I have an application that ran on mod_perl 1.3 and perl 5.8 for a long time, that I recently ported over to a Fedora 9 box, thus moving it to mod_perl 2.0 and perl 5.10.


Under this new environment, I am getting some of the most bizarre and insidious perl core errors I've ever seen in my 15 years of using perl.  Here's a sampling:

Attempt to free unreferenced scalar: SV 0xbd266be4, Perl interpreter: 0xba01c410 at /usr/lib/perl5/vendor_perl/5.10.0/HTML/Mason/Component.pm line 147.

panic: attempt to copy value 20 to a freed scalar bd49dffc
Use of freed value in iteration
panic: free from wrong pool

Not to mention countless application errors involving dereferencing, where things that are supposed to be arrays and hashrefs have magically turned into strings and key values, and vice versa.


Now I realize this is not an issue with mod_perl itself.  Obviously something is doing a massive fandango on core and corrupting the Perl stack/arena over time.  Note that running Apache with MaxRequestsPerChild = 1 seems to mitigate the issue, so it's a problem that occurs at runtime.


My problem is that I don't even know where or how to start tracing or debugging such an issue to determine precisely what is scribbling on perl's memory.  If this was a standalone app, it would be simple enough to run it through gdb and trace everything out, but in a mod_perl environment....


Any advice on how to proceed is greatly appreciated.

--
Stephen Clouse <>

------=_Part_2726_14093633.1215537815428--

Re: How to debug bizarre memory corruption in mod_perl

am 08.07.2008 19:55:31 von Frank Wiles

On Tue, 8 Jul 2008 12:23:35 -0500
"Stephen Clouse" wrote:

> My problem is that I don't even know where or how to start tracing or
> debugging such an issue to determine precisely what is scribbling on
> perl's memory. If this was a standalone app, it would be simple
> enough to run it through gdb and trace everything out, but in a
> mod_perl environment....
>
> Any advice on how to proceed is greatly appreciated.

Hey Stephen,

This definitely sounds like a problem you're going to need a
debugger to figure out. Check out this article I wrote on
debugging and profiling mod_perl applications:

http://www.perl.com/pub/a/2006/02/09/debug_mod_perl.html

You'll need to install the Apache::DB module from CPAN, but
once you get it setup and running it gives you access to
the full Perl debugger.

Hope this helps!

-------------------------------------------------------
Frank Wiles, Revolution Systems, LLC.
Personal : frank@wiles.org http://www.wiles.org
Work : frank@revsys.com http://www.revsys.com

Re: How to debug bizarre memory corruption in mod_perl

am 08.07.2008 20:04:26 von Perrin Harkins

On Tue, Jul 8, 2008 at 1:23 PM, Stephen Clouse wrote:
> I have an application that ran on mod_perl 1.3 and perl 5.8 for a long time,
> that I recently ported over to a Fedora 9 box, thus moving it to mod_perl
> 2.0 and perl 5.10.

Are you running prefork, or threaded? Did you change anything else?
The kind of problems you're seeing usually come from bad XS code. You
might try reverting to Perl 5.8 or mod_perl 1.3 to determine what is
causing the problem.

- Perrin

Re: How to debug bizarre memory corruption in mod_perl

am 08.07.2008 20:28:15 von Stephen Clouse

------=_Part_2990_19663096.1215541695607
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Tue, Jul 8, 2008 at 1:04 PM, Perrin Harkins wrote:

> Are you running prefork, or threaded?


prefork. It's a stock Fedora 9 Apache/mod_perl.


> Did you change anything else?


Other than installing my app, no.


> The kind of problems you're seeing usually come from bad XS code.


That's my guess, too, but I don't know how to narrow it down. It's a long
list:

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Compress/ Raw/Zlib/Zlib.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Cwd/Cwd.s o
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Data/Dump er/Dumper.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Digest/MD 5/MD5.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcn tl.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/File/Glob /Glob.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util /Util.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Math/BigI nt/FastCalc/FastCalc.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/MIME/Base 64/Base64.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/POSIX/POS IX.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Socket/So cket.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Storable/ Storable.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Sys/Hostn ame/Hostname.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Time/HiRe s/HiRes.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Const/Const.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Log/Log.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Module/Module.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestIO/RequestIO.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestRec/RequestRec.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestUtil/RequestUtil.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/ServerUtil/ServerUtil.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/SubRequest/SubRequest.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Brigade/Brigade.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/BucketAlloc/BucketAlloc.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Pool/Pool.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Apache2/Apache2.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Cookie/Cookie.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Param/Param.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Request.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Table/Table.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/BSD/Resource/Resource.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Date/Calc/Calc.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/DBD/mysql/mysql.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/DBI/DBI.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Digest/SHA1/SHA1.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/GD/GD.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/HTML/Parser/Parser.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Net/DNS/DNS.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/OSSP/uuid/uuid.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Params/Validate/Validate.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Text/CSV_XS/CSV_XS.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXML/Common/Common.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXML/LibXML.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXSLT/LibXSLT.so

You
> might try reverting to Perl 5.8 or mod_perl 1.3 to determine what is
> causing the problem.
>

Fedora currently ships with mod_perl 2.0 and perl 5.10. No good way to
revert there :)

--
Stephen Clouse

------=_Part_2990_19663096.1215541695607
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Tue, Jul 8, 2008 at 1:04 PM, Perrin Harkins <> wrote:


Are you running prefork, or threaded?

prefork.  It's a stock Fedora 9 Apache/mod_perl.
 

Did you change anything else?

Other than installing my app, no. 
 


The kind of problems you're seeing usually come from bad XS code.

That's my guess, too, but I don't know how to narrow it down.  It's a long list:

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Compress/ Raw/Zlib/Zlib.so

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Cwd/Cwd.s o
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Data/Dump er/Dumper.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Digest/MD 5/MD5.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcn tl.so

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/File/Glob /Glob.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util /Util.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Math/BigI nt/FastCalc/FastCalc.so

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/MIME/Base 64/Base64.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/POSIX/POS IX.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Socket/So cket.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Storable/ Storable.so

/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Sys/Hostn ame/Hostname.so
/usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Time/HiRe s/HiRes.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Const/Const.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Log/Log.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/Module/Module.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestIO/RequestIO.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestRec/RequestRec.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/RequestUtil/RequestUtil.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/ServerUtil/ServerUtil.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Apache2/SubRequest/SubRequest.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Brigade/Brigade.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/BucketAlloc/BucketAlloc.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Pool/Pool.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Apache2/Apache2.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Cookie/Cookie.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Param/Param.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Request/Request.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/APR/Table/Table.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/BSD/Resource/Resource.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Date/Calc/Calc.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/DBD/mysql/mysql.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/DBI/DBI.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Digest/SHA1/SHA1.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/GD/GD.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/HTML/Parser/Parser.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Net/DNS/DNS.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/OSSP/uuid/uuid.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Params/Validate/Validate.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/Text/CSV_XS/CSV_XS.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXML/Common/Common.so

/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXML/LibXML.so
/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi/au to/XML/LibXSLT/LibXSLT.so


You

might try reverting to Perl 5.8 or mod_perl 1.3 to determine what is

causing the problem.


Fedora currently ships with mod_perl 2.0 and perl 5.10.  No good way to revert there :)

--
Stephen Clouse <>

------=_Part_2990_19663096.1215541695607--

Re: How to debug bizarre memory corruption in mod_perl

am 08.07.2008 20:33:53 von Fred Moyer

Stephen Clouse wrote:
> I will preface this message with this: this is not a mod_perl bug or
> problem, but it involves a mod_perl application, so this is probably a
> good place to get advice from experienced mod_perl users/developers.
>
> I have an application that ran on mod_perl 1.3 and perl 5.8 for a long
> time, that I recently ported over to a Fedora 9 box, thus moving it to
> mod_perl 2.0 and perl 5.10.
>
> Under this new environment, I am getting some of the most bizarre and
> insidious perl core errors I've ever seen in my 15 years of using perl.
> Here's a sampling:
>
> Attempt to free unreferenced scalar: SV 0xbd266be4, Perl interpreter:
> 0xba01c410 at /usr/lib/perl5/vendor_perl/5.10.0/HTML/Mason/Component.pm
> line 147.
> panic: attempt to copy value 20 to a freed scalar bd49dffc
> Use of freed value in iteration
> panic: free from wrong pool
>
> Not to mention countless application errors involving dereferencing,
> where things that are supposed to be arrays and hashrefs have magically
> turned into strings and key values, and vice versa.

For what it is worth, I spent a couple hours trying to a development
setup running on FC9 with 5.10.0, and gave up because of oddball errors.

Perl 5.10.0 is considered to be a testing release
(http://cpan.perl.org/src/README.html), and FC9 is still pretty fresh.

I would suggest going with FC8 and 5.8.8 until FC9 has been out in the
wild for a while, and perhaps waiting until 5.10.1 is released. You may
be able to figure out exactly what the problem is, but it may make more
sense to use FC8 and 5.8.8.

Re: How to debug bizarre memory corruption in mod_perl

am 08.07.2008 20:40:04 von Perrin Harkins

On Tue, Jul 8, 2008 at 2:28 PM, Stephen Clouse wrote:
>> You
>> might try reverting to Perl 5.8 or mod_perl 1.3 to determine what is
>> causing the problem.
>
> Fedora currently ships with mod_perl 2.0 and perl 5.10. No good way to
> revert there :)

I don't use vendor packages for this stuff. If a web app is the
primary purpose of this machine, using a generic compile that Red Hat
made to try to please the broadest possible audience is likely to be
worse than your own compile, even if you just take defaults.

At this point, since you didn't change your app, you know that the
problem is either mod_perl 2, perl 5.10, or the Fedora compile. If
you do your own compile, that will let you test if it's Fedora's
problem. Then you can try swapping out the others. Unless you're
familiar with debugging perl guts, I don't really see another way for
you to find the problem.

- Perrin

Re: How to debug bizarre memory corruption in mod_perl

am 09.07.2008 10:09:05 von David Kaufman

"Stephen Clouse" wrote:
> Under [mod_perl 2 and perl 5.10 on Fedora 9] I am getting some of the
> most bizarre and insidious perl core errors I've ever seen in my 15
> years of using perl.
>
> Attempt to free unreferenced scalar: SV 0xbd266be4, Perl interpreter:
> 0xba01c410 at /usr/lib/perl5/vendor_perl/5.10.0/HTML/Mason/Component.pm
> line
> 147.
> panic: attempt to copy value 20 to a freed scalar bd49dffc
> Use of freed value in iteration
> panic: free from wrong pool
>
> Not to mention countless application errors involving dereferencing.

Dereferencing demons, eh? Your error rang a bell with me. But it wasn't
until I saw List/Util/Util.so in your follow-up post that I remembered,
List::Util did that same scary crashing thing to me a while back while I
was debugging krang (which is mod_perl 1.3x-based).

It boiled down to the (IMO) senseless and unnecessary use of weak
referrences somewhere deep in the dark bowels of the Scalar-List-Utils
package. I'd read somewhere that weak references were not all that stable
in certain recent versions of perl, so when I saw all the weakening being
done in there (and all the XS bugs the module has had to fix, in its change
log:

http://search.cpan.org/src/GBARR/Scalar-List-Utils-1.19/Chan ges

At the time, upgrading the module to the latest release didn't stop my big
scary memory reference errors. So I read through the code that used the
module and was astonished at why the module was being used: the *one* line
of code in the entire module that I was troubleshooting that *depended* on
List::Util was a single, simple call to its exported method: first()

What does first() do? It invokes kilobytes of fast, compiled XS code to
....huh? Return to me the first element in a list I pass to it that returns
true for a code block I pass to it? Yup. Like this:

# from the POD doco at
#
http://search.cpan.org/~gbarr/Scalar-List-Utils-1.19/lib/Lis t/Util.pm#DESCRIPTION

$foo = first { defined($_) } @list; # first defined value in @list


Who needs to install a CPAN module to do that? I personally would have
written it as:

$foo = (grep defined, @list)[0]; # first defined value in @list


But thats kind of non-obvious to the programmer who finds it later (if they
dont read the comment, that is). You could also simply replace "first"
with "grep" (and a pair of parens) and get the same effect:

($foo) = grep { defined($_) } @list; # first defined value in @list

(at the cost of one extra byte and some wasted cpu cycles if the compiler
doesn't notice that the lvalue is a list of length one, and lets grep
process the whole list anyway, even after it finds and assigns a defined
element in there).

IMO, even this would be better than loading List::Utils and calling
first():

my $foo;
for (@list) {
next unless defined($_);
$foo = $_;
last;
}

So I fixed my bug by writing a line or two of perl to in order to remove
one call to the List::Util module's first() function.


> My problem is that I don't even know where or how to start tracing or
> debugging such an issue to determine precisely what is scribbling on
> perl's
> memory.

Starting from your error message (line 147 of HTML::Mason::Component) it
appears HTML::Mason is calling a "dynamic method" method (one named in a
variable). No help there. Okay, what else is HTML::Mason::Component
using? What libraries has it loaded? Is List::Utils being used?

This looked suspicious to me:

use HTML::Mason::Tools qw(absolute_comp_path can_weaken);

Just because you "can_weaken" a reference, does that mean you should? Sure
enough HTML::Mason::Tools loads Scalar::Util apparently to do some
reference weakening.

I'd check my Mason component for use of the functions that the
Scalar-List-Utils modules provide:

List::Util

first max maxstr min minstr reduce shuffle sum

Scalar::Util

blessed dualvar isweak readonly refaddr reftype
tainted weaken isvstring looks_like_number set_prototype

And see if rewriting these in pure perl helps. Also, if it does, but would
require changing code that you'd rather not monkey with, it looks like
there is a pure-perl version of the module that can be installed by passing
a -pm option to Makefile.PL:

perl Makefile.PL -pm
make
make test
make install

Anyway, I hope somehow, some of this helps!

-dave

Re: How to debug bizarre memory corruption in mod_perl

am 09.07.2008 14:23:13 von Brock Diegel

On 9 Jul 2008, at 09:09, David Kaufman wrote:
> # from the POD doco at
> #
> http://search.cpan.org/~gbarr/Scalar-List-Utils-1.19/lib/Lis t/Util.pm#DESCRIPTION
>
> $foo = first { defined($_) } @list; # first defined value in @list
>
>
> Who needs to install a CPAN module to do that? I personally would
> have
> written it as:
>
> $foo = (grep defined, @list)[0]; # first defined value in @list


Bear in mind that first may be much more efficient if the list is
large and/or the test is expensive:

$ cat foo.pl
use List::Util qw( first );

sub even {
my ( $where, $x ) = @_;
print "$where is checking $x\n";
return $x % 2 == 0;
}

my @in = ( 1, 2, 3, 4, 5 );

my $first_even = first { even( 'first', $_ ) } @in;
my $grep_even = ( grep { even( 'grep', $_ ) } @in )[0];

print "$first_even, $grep_even\n";

$ perl foo.pl
first is checking 1
first is checking 2
grep is checking 1
grep is checking 2
grep is checking 3
grep is checking 4
grep is checking 5
2, 2

I'm not suggesting that necessarily applies in this case - just a
general observation.

--
Andy Armstrong, Hexten

Re: How to debug bizarre memory corruption in mod_perl

am 09.07.2008 20:43:26 von Frank Wiles

On Wed, 9 Jul 2008 13:23:13 +0100
Andy Armstrong wrote:

> On 9 Jul 2008, at 09:09, David Kaufman wrote:
> > # from the POD doco at
> > #
> > http://search.cpan.org/~gbarr/Scalar-List-Utils-1.19/lib/Lis t/Util.pm#DESCRIPTION
> >
> > $foo = first { defined($_) } @list; # first defined value in @list
> >
> >
> > Who needs to install a CPAN module to do that? I personally would
> > have
> > written it as:
> >
> > $foo = (grep defined, @list)[0]; # first defined value in @list
>
>
> Bear in mind that first may be much more efficient if the list is
> large and/or the test is expensive

Agree on the efficiency. I worked with a company on a large
mod_perl application (300K+ lines of code) that used a particular
function VERY often, that took an array and returned all the
unique values.

It did this with the common Perl Cookbook way of putting everything
into a hash and returning the keys(). I switched that function
to using List::MoreUtils::uniq() and they saw almost a 10% speed
improvement to their entire application. Granted this was a special
case because of how often that particular function was used (which
was a bad design decision in the first place), but sometimes
using these types of modules is useful/necessary even if the
normal "Perl core" way of doing it is relatively simple.

For example, if we use the technique above vs first() you get:

100 items in the list:
Rate Grep first
Grep 85470/s -- -74%
first 331126/s 287% --

5000 items in the list:
Rate Grep first
Grep 1743/s -- -99%
first 125000/s 7073% --

So even for relatively small lists it can be a huge performance
win.

-------------------------------------------------------
Frank Wiles, Revolution Systems, LLC.
Personal : frank@wiles.org http://www.wiles.org
Work : frank@revsys.com http://www.revsys.com

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 03:23:12 von Stephen Clouse

------=_Part_13148_32477243.1215652992502
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Well, thank you for your advice, gentlemen. It got me on the right track,
and I did manage to figure out the issue today. You may or may not be
surprised to find it was this:

my $foo = "bar" if $baz;

Apparently one of the previous programmers left about 100 such constructs
littered about the Perl and Mason code. Fixing them cleared up all the
bizarre issues.

We had Perl::Critic for the Perl side of the app, and I've done some hacks
to criticize the Mason code, but someone had disabled the
ProhibitConditionalDeclarations policy. *facepalm*

It's interesting that this didn't manifest under Perl 5.8. Not sure if it's
worth trying to develop a test case, since my...if falls into the "never do
this" category anyway.

--
Stephen Clouse

------=_Part_13148_32477243.1215652992502
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Well, thank you for your advice, gentlemen.  It got me on the right track, and I did manage to figure out the issue today.  You may or may not be surprised to find it was this:

my $foo = "bar" if $baz;


Apparently one of the previous programmers left about 100 such constructs littered about the Perl and Mason code.  Fixing them cleared up all the bizarre issues.

We had Perl::Critic for the Perl side of the app, and I've done some hacks to criticize the Mason code, but someone had disabled the ProhibitConditionalDeclarations policy.  *facepalm*


It's interesting that this didn't manifest under Perl 5.8.  Not sure if it's worth trying to develop a test case, since my...if falls into the "never do this" category anyway.

--
Stephen Clouse <>

------=_Part_13148_32477243.1215652992502--

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 06:05:19 von Perrin Harkins

On Wed, Jul 9, 2008 at 9:23 PM, Stephen Clouse wrote:
> We had Perl::Critic for the Perl side of the app, and I've done some hacks
> to criticize the Mason code, but someone had disabled the
> ProhibitConditionalDeclarations policy.

I'm thrilled to hear that this ultimately was valuable because I
suggested that policy. It would be great if you'd share your hack to
make Critic work on Mason code somewhere.

> It's interesting that this didn't manifest under Perl 5.8.

And a little scary, since some people definitely have this bug and the
warning for it in 5.10 was removed before release.

- Perrin

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 06:17:32 von Stephen Clouse

------=_Part_13819_8376988.1215663452748
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Wed, Jul 9, 2008 at 11:05 PM, Perrin Harkins wrote:

> I'm thrilled to hear that this ultimately was valuable because I
> suggested that policy. It would be great if you'd share your hack to
> make Critic work on Mason code somewhere.


Oh, yeah, sure. Here's my test script. It just takes the compiled Mason
object and runs it through Critic. Also, the last half is shamelessly
cribbed from Test::Perl::Critic.

This is less useful than it seems because Mason's object code output doesn't
pass Perl::Critic itself :) But it's probably a start for someone to
improve upon -- maybe modulize it and throw it on CPAN. Or maybe improve
Mason's code output so it does pass a critique.

#!/usr/bin/perl
use strict;
use warnings;
no warnings qw(once);

use File::Find ();
use HTML::Mason::Compiler::ToObject ();
use Perl::Critic ();
use Test::More;

my $critic = Perl::Critic->new(
-profile => 't/perlcriticrc',
);

local *HTML::Mason::Commands::r = \"0";

my @files;
my $wanted = sub {
return if -d $_;
return if $_ eq 'favicon.ico';
return if $File::Find::name =~ /\.svn|images|javascript|css/;
push @files, $File::Find::name;
};
File::Find::find($wanted, 'htdocs');

plan tests => scalar(@files);

foreach my $file (@files) {
my(@vios);
eval {
my $src;
{ local $/ = undef;
open(my $foo, $file) or die "Couldn't open $file: $!";
$src = <$foo>;
}

my $compiler = HTML::Mason::Compiler::ToObject->new;
my $object_code = $compiler->compile(
comp_source => \$src,
name => $file,
comp_path => 'htdocs',
);

@vios = $critic->critique($object_code, -severity => 1);
};

if ($@) {
fail($file);
diag("\n");
diag(qq{Perl::Critic had errors in "$file":});
diag(qq{\t$@});
} elsif (@vios) {
fail($file);
diag("\n");
diag(qq{Perl::Critic found these violations in "$file":});
my $verbose = $critic->config->verbose();
Perl::Critic::Violation::set_format( $verbose );
foreach my $vio (@vios) { diag("$vio") }
} else {
pass($file);
}
}

--
Stephen Clouse

------=_Part_13819_8376988.1215663452748
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Wed, Jul 9, 2008 at 11:05 PM, Perrin Harkins <> wrote:


I'm thrilled to hear that this ultimately was valuable because I

suggested that policy.  It would be great if you'd share your hack to

make Critic work on Mason code somewhere.

Oh, yeah, sure.  Here's my test script.  It just takes the compiled Mason object and runs it through Critic.  Also, the last half is shamelessly cribbed from Test::Perl::Critic.


This is less useful than it seems because Mason's object code output doesn't pass Perl::Critic itself :)  But it's probably a start for someone to improve upon -- maybe modulize it and throw it on CPAN.  Or maybe improve Mason's code output so it does pass a critique.


#!/usr/bin/perl
use strict;
use warnings;
no warnings qw(once);

use File::Find ();
use HTML::Mason::Compiler::ToObject ();
use Perl::Critic ();
use Test::More;

my $critic = Perl::Critic->new(

  -profile => 't/perlcriticrc',
);

local *HTML::Mason::Commands::r = \"0";

my @files;
my $wanted = sub {
  return if -d $_;
  return if $_ eq 'favicon.ico';
  return if $File::Find::name =~ /\.svn|images|javascript|css/;

  push @files, $File::Find::name;
};
File::Find::find($wanted, 'htdocs');

plan tests => scalar(@files);

foreach my $file (@files) {
  my(@vios);
  eval {
    my $src;
    { local $/ = undef;

      open(my $foo, $file) or die "Couldn't open $file: $!";
      $src = <$foo>;
    }

    my $compiler = HTML::Mason::Compiler::ToObject->new;
    my $object_code = $compiler->compile(

      comp_source => \$src,
      name => $file,
      comp_path => 'htdocs',
    );

    @vios = $critic->critique($object_code, -severity => 1);
  };

  if ($@) {
    fail($file);

    diag("\n");
    diag(qq{Perl::Critic had errors in "$file":});
    diag(qq{\t$@});
  } elsif (@vios) {
    fail($file);
    diag("\n");
    diag(qq{Perl::Critic found these violations in "$file":});

    my $verbose = $critic->config->verbose();
    Perl::Critic::Violation::set_format( $verbose );
    foreach my $vio (@vios) { diag("$vio") }
  } else {
    pass($file);
  }
}


--
Stephen Clouse <>

------=_Part_13819_8376988.1215663452748--

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 11:52:26 von Brock Diegel

On 10 Jul 2008, at 05:05, Perrin Harkins wrote:
>> It's interesting that this didn't manifest under Perl 5.8.
>
> And a little scary, since some people definitely have this bug and the
> warning for it in 5.10 was removed before release.


Yeah, I'm thinking this thread should migrate to p5p for that reason.
While undefined behaviour can nominally include flying butt monkeys I
don't think it's desirable for it to cause rampant memory corruption.

--
Andy Armstrong, Hexten

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 18:23:01 von David Kaufman

Hi Stephen,

"Stephen Clouse" wrote ...
> ...I did manage to figure out the issue today. You may or may not be
> surprised to find it was this:
>
> my $foo = "bar" if $baz;

Yikes! My bad :-) It must've been a different scary memory error that I
encountered with List::Util.

> Apparently one of the previous programmers left about 100 such constructs
> littered about the Perl and Mason code. Fixing them cleared up all the
> bizarre issues.

I too was "one of those guys" who liberally littered his code with the
construct:

my $foo = 'bar' if $baz;

I unlearned to do it too, a few months back, which must have been why your
errors "rang a bell" with me. My co-workers had to track down that is was
my {declaration + assignment + conditional} that was throwing the scary
memory errors. I never saw it. I'd been doing it for years, and prior to
that I had no idea it was A Bad Thing to do, and I said as much to them,
"it's always worked fine for me!"

I wish it would still DWIM, and by that I mean the compiler should detect
my declaration + assignment + conditional and rewrite it for me as what I
meant which was simply:

my $foo = $baz ? 'bar' : undef;

That's how I've been rewriting these since then.

It seems a no-brainer that when no-brain people like me write this, they
mean to make the assignment conditional, not declaration of the variable,
so that:

declaration + assignment + conditional == declaration + (conditional
assignment)

I've already (finally) unlearned to do that, but I agree with Andy that the
cost of people's ignorance (especially doing something that's worked as
expected for so long) shouln't cause "rampant memory corruption". It
should maybe DWIM or die or warn, but not dump core :-)

-dave

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 18:35:58 von Mark Hedges

On Thu, 10 Jul 2008, David Kaufman wrote:
>
> my $foo = 'bar' if $baz;
>
> I wish it would still DWIM, and by that I mean the compiler should detect
> my declaration + assignment + conditional and rewrite it for me as what I
> meant which was simply:
>
> my $foo = $baz ? 'bar' : undef;
>

I disagree. In the first, you are telling perl that you
want to create a symbol if a certain condition is true.
Maybe under some conditions you don't want to create that
symbol. Consider the same logic applied to hash assignment:

my %foo;
$foo{bar} = 'baz' if $biz;
frob() if exists $foo{bar};

You would expect that $foo{bar} would not exist if $biz was
false. But under your recommendation, it would exist. This
is not the way it should behave.

Mark

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 19:09:49 von Brock Diegel

On 10 Jul 2008, at 17:23, David Kaufman wrote:
> I've already (finally) unlearned to do that, but I agree with Andy
> that the
> cost of people's ignorance (especially doing something that's worked
> as
> expected for so long) shouln't cause "rampant memory corruption". It
> should maybe DWIM or die or warn, but not dump core :-)


Indeed. I've taken it to perl5-porters[1]. I'm not sure if it's a
known problem with 5.10.0 but I certainly hadn't heard of it.

[1] http://markmail.org/message/yfxkc6sbw2ydvcjz

--
Andy Armstrong, Hexten

Re: How to debug bizarre memory corruption in mod_perl

am 10.07.2008 19:27:19 von David Kaufman

Hi Mark,

"Mark Hedges" wrote:
>
> David Kaufman wrote:
>
>> my $foo = 'bar' if $baz;
>>
>> I wish it would still DWIM, and by that I mean the compiler should
>> detect
>> my declaration + assignment + conditional and rewrite it for me as what
>> I
>> meant which was simply:
>>
>> my $foo = $baz ? 'bar' : undef;
>
> I disagree. In the first, you are telling perl that you
> want to create a symbol if a certain condition is true.
> Maybe under some conditions you don't want to create that
> symbol.

Fair enough. I've never felt the need to (or read anyone elses code that
chose to) conditionally declare a lexically local variable, but I agree
thatm if someone felt the need to do so, then:

my $foo if $necessary;

shouldn't behave any differently than:

my $foo = 'bar' if $necessary;

So I'd be happy with a warning. And, you know, not corrupting memory...
:-)

-dave