What does "PmmREFCNT_dec: REFCNT reduced below 0" mean?

I had to make perl very upset because it gives me an error message that is not logged in perldiag :

PmmREFCNT_dec: REFCNT decreased below 0 for 53a6930 !.

Depending on your mood, this is sometimes accompanied by:

*** glibc detected *** / usr / bin / perl: double free or corrupt (! prev): 0x0000000004e58a60 *

... or more explicitly:

Segmentation error

This is obviously fatal, but I also tested it for availability. When using Try::Tiny I will always catch the error in one place, but when you do not use it, a few more instructions are executed before the failure. In addition, despite the fact that my module is completely deterministic, and I am sure that all dependencies also occur, an error does not occur all the time.

Unfortunately, the module that gives me this problem is huge, with lots of dependencies, and I could not reproduce the problem with a smaller example. Therefore, I cannot ask for help debugging it, but if someone familiar with the internal components of Perl knows the circumstances in which this error occurs, it can help me (or anyone else to ever see this message) source of the problem and / or workaround.

In case this is useful, the general idea is as follows. I have two classes, call them Thing and SetOfThings . SetOfThings has an attribute that is a collection of Thing instances. Both classes also have an explode method that does something like this:

 # SetOfThings sub explode { my $self = shift; my $new = dclone $self; delete $new->{'some_attribute'}; $new->set_of_things( map { $_->explode } $self->constraints ); return $new; } # Thing sub explode { my $self = shift; return map { new Thing( do_something_fancy ) } keys %$self; } 

Typically, an error occurs when calling SetOfThings::explode or when calling SetOfThings::set_of_things as the receiver.

Edit: Backtrace

I do not believe that I am competent enough to interpret it, but I received a return line from gdb :

 #0 0x00007ffff70a6094 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff70a76a8 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00007ffff70aab1c in free () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x00007ffff7b0869b in Perl_hv_undef_flags () from /usr/lib/libperl.so.5.14 #4 0x00007ffff7b1ae66 in Perl_sv_clear () from /usr/lib/libperl.so.5.14 #5 0x00007ffff7b1b292 in Perl_sv_free2 () from /usr/lib/libperl.so.5.14 #6 0x00007ffff7b04bc3 in Perl_hv_free_ent () from /usr/lib/libperl.so.5.14 #7 0x00007ffff7b04e6e in ?? () from /usr/lib/libperl.so.5.14 #8 0x00007ffff7b08683 in Perl_hv_undef_flags () from /usr/lib/libperl.so.5.14 #9 0x00007ffff7b1ae66 in Perl_sv_clear () from /usr/lib/libperl.so.5.14 #10 0x00007ffff7b1b292 in Perl_sv_free2 () from /usr/lib/libperl.so.5.14 #11 0x00007ffff7b42cef in Perl_leave_scope () from /usr/lib/libperl.so.5.14 #12 0x00007ffff7b11112 in Perl_pp_leave () from /usr/lib/libperl.so.5.14 #13 0x00007ffff7b0bce6 in Perl_runops_standard () from /usr/lib/libperl.so.5.14 #14 0x00007ffff7aad815 in perl_run () from /usr/lib/libperl.so.5.14 #15 0x0000000000400f89 in main () 

Edit 2: backgrrace Valgrind

This is what I got from running valgrind . Although I'm still not sure what is going on, at least now I know who to blame. :-)

 ==27226== Invalid free() / delete / delete[] / realloc() ==27226== at 0x4C27D4E: free (vg_replace_malloc.c:427) ==27226== by 0xA138F42: PmmREFCNT_dec (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so) ==27226== by 0xA11D3FA: XS_XML__LibXML__Node_DESTROY (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so) ==27226== by 0x4EE770B: Perl_pp_entersub (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4E7AB90: Perl_call_sv (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEDBD8: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4ED7BC2: Perl_hv_free_ent (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4ED7E6D: ??? (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EDB682: Perl_hv_undef_flags (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEDE65: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2) ==27226== Address 0x17d0b710 is 0 bytes inside a block of size 32 free'd ==27226== at 0x4C27D4E: free (vg_replace_malloc.c:427) ==27226== by 0xA138F42: PmmREFCNT_dec (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so) ==27226== by 0xA11D3FA: XS_XML__LibXML__Node_DESTROY (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so) ==27226== by 0x4EE770B: Perl_pp_entersub (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4E7AB90: Perl_call_sv (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEDBD8: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4ED7BC2: Perl_hv_free_ent (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EDA919: Perl_hv_common (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4F0EEC7: Perl_pp_delete (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4EDECE5: Perl_runops_standard (in /usr/lib/libperl.so.5.14.2) ==27226== by 0x4E80814: perl_run (in /usr/lib/libperl.so.5.14.2) 
+6
source share
1 answer

Quote ikegami comment because I could not formulate it better:

This is a bug in Perl or in the XS module. A variable should be freed when its reference count reaches zero, but something tried to decrease the reference count of variables when it is already zero.

As the result of valgrind shows, in this particular case, the problem is in XML::LibXML .

I believe that updating XML::LibXML , as suggested by Sinan Ünür , once the problem is understood and fixed, is the way to go. Unfortunately, upgrading from 2.0001 (stable version of Debian) to 2.0116 (version CPAN) did not fix it.

What was the problem, finally, was to modify SetOfThings::explode so that it would create a new instance and copy the attributes it needed, rather than clone the current instance, and deleting the attributes is not required:

 sub explode { my $self = shift; my $new = __PACKAGE__->new; $new->some_attribute('whatever'); $new->set_of_things( map { $_->explode } $self->constraints ); return $new; } 

One of the attributes of the SetOfThings object that was cloned, then deleted, was the DOM, which XML::LibXML did not evaluate explicitly. Thanks to this knowledge and comments, I was finally able to reproduce my problem in a very small script and post an error report:

 #!/usr/bin/perl use strict; use warnings; use Clone 'clone'; use XML::LibXML; my $dom1 = new XML::LibXML::Document; my $dom2 = clone $dom1; 

As pointed out by ikegs, cloning a Perl variable does not copy the underlying C structure used by the library. But XML::LibXML provides the cloneNode method, so changing the last line to

 my $dom2 = $dom1->cloneNode(1) 

gives the desired result.

+3
source

All Articles