Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory leak in 5.24.1, regression #15966

Closed
p5pRT opened this issue Apr 27, 2017 · 11 comments
Closed

memory leak in 5.24.1, regression #15966

p5pRT opened this issue Apr 27, 2017 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 27, 2017

Migrated from rt.perl.org#131219 (status was 'resolved')

Searchable as RT131219$

@p5pRT
Copy link
Author

p5pRT commented Apr 27, 2017

From glebius@FreeBSD.org

Created by glebius@FreeBSD.org

There is a memory leak regression in perl 5.24.1, not present in
perl 5.22.3. We managed to repropuce it in a small cyclic program
that uses Net​::SNMP module. Note, that problem doesn't belong to
the module, it is in the core. When script is run with perl 5.24,
the perl process memory quickly grows. When script is run with
perl 5.22 the perl process memory is constant. The same Net​::SNMP
module is used in both scenarios.

The script to reproduce​:

use strict;
use warnings;

use constant OID_IFx_base => '1.3.6.1.2.1.31.1.1';
use constant OID_IFx => {
  OID_IFx_base.".1.1" => 'IFace',
  OID_IFx_base.".1.6" => 'HCInOctets',
  OID_IFx_base.".1.10" => 'HCOutOctets',
  OID_IFx_base.".1.15" => 'HighSpeed',
};

use Net​::SNMP qw(​:snmp);

my $done = 0;
map {
  $SIG{$_} = sub { $done++ };
} qw (INT QUIT HUP);

printf("%s\n", $$);

while (! $done)
{
  my $oid_table = OID_IFx;
  my @​oid_keys = oid_lex_sort(keys %$oid_table);
  my $table = [ ];
  my $toid;
  my $result;
  my ($session, $error) = Net​::SNMP->session(
  -hostname => '127.0.0.1',
  -community => 'public',
  -timeout => 5, # seconds
  -retries => 3,
  -nonblocking => 0,
  -translate => [-octetstring => 0],
  -version => 'snmpv2c',
  );
  die sprintf("ERROR​: %s\n", $error) unless defined $session;

  while (($toid = shift @​oid_keys)) {
  $result = $session->get_table(-baseoid => $toid,
  -maxrepetitions => 1,);
  defined $result or die sprintf("ERROR​: %s\n", $session->error());

  }

  select(undef, undef, undef, 0.01);
}

Perl Info

Flags:
    category=core
    severity=high

Site configuration information for perl 5.24.1:

Configured by perl at Sat Jan 14 20:05:52 UTC 2017.

Summary of my perl5 (revision 5 version 24 subversion 1) configuration:
   
  Platform:
    osname=freebsd, osvers=12.0-current, archname=amd64-freebsd-thread-multi
    uname='freebsd head-amd64-default-job-02 12.0-current freebsd 12.0-current r316946 amd64 '
    config_args='-sde -Dprefix=/usr/local -Dlibperl=libperl.so.5.24.1 -Darchlib=/usr/local/lib/perl5/5.24/mach -Dprivlib=/usr/local/lib/perl5/5.24 -Dman3dir=/usr/local/lib/perl5/5.24/perl/man/man3 -Dman1dir=/usr/local/lib/perl5/5.24/perl/man/man1 -Dsitearch=/usr/local/lib/perl5/site_perl/mach/5.24 -Dsitelib=/usr/local/lib/perl5/site_perl -Dscriptdir=/usr/local/bin -Dsiteman3dir=/usr/local/lib/perl5/site_perl/man/man3 -Dsiteman1dir=/usr/local/lib/perl5/site_perl/man/man1 -Ui_malloc -Ui_iconv -Uinstallusrbinperl -Dusenm=n -Dcc=cc -Duseshrplib -Dinc_version_list=none -Dcf_by=perl -Dcf_email=perl@FreeBSD.org -Dcf_time=Sat Jan 14 20:05:52 UTC 2017 -Alddlflags=-L/wrkdirs/usr/ports/lang/perl5.24/work/perl-5.24.1 -L/usr/local/lib/perl5/5.24/mach/CORE -lperl -Dshrpldflags=$(LDDLFLAGS:N-L/wrkdirs/usr/ports/lang/perl5.24/work/perl-5.24.1:N-L/usr/local/lib/perl5/5.24/mach/CORE:N-lperl) -Wl,-soname,$(LIBPERL:R) -Doptimize=-O2 -pipe  -fstack-protector -fno-strict-aliasing -Dusedtrace -Ui_gdbm -Dusemultiplicity=y -Duse64bitint -Dusethreads=y -Dusemymalloc=n'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_FORTIFY_SOURCE=2',
    optimize='-O2 -pipe -fstack-protector -fno-strict-aliasing',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion='', gccversion='4.2.1 Compatible FreeBSD Clang 4.0.0 (tags/RELEASE_400/final 297347)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-lpthread -Wl,-E  -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib /usr/bin/../lib/clang/4.0.0/lib /usr/lib
    libs=-lpthread -lm -lcrypt -lutil
    perllibs=-lpthread -lm -lcrypt -lutil
    libc=, so=so, useshrplib=true, libperl=libperl.so.5.24.1
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='  -Wl,-R/usr/local/lib/perl5/5.24/mach/CORE'
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib/perl5/5.24/mach/CORE -lperl -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.24.1:
    /usr/local/lib/perl5/site_perl/mach/5.24
    /usr/local/lib/perl5/site_perl
    /usr/local/lib/perl5/5.24/mach
    /usr/local/lib/perl5/5.24


Environment for perl 5.24.1:
    HOME=/home/glebius
    LANG=ru_RU.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/bin:/sbin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/glebius/bin
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2017

From @iabyn

On Thu, Apr 27, 2017 at 01​:54​:14PM -0700, Gleb Smirnoff wrote​:

There is a memory leak regression in perl 5.24.1, not present in
perl 5.22.3. We managed to repropuce it in a small cyclic program
that uses Net​::SNMP module. Note, that problem doesn't belong to
the module, it is in the core. When script is run with perl 5.24,
the perl process memory quickly grows. When script is run with
perl 5.22 the perl process memory is constant. The same Net​::SNMP
module is used in both scenarios.

Is it possible for you to reduce this further to something that doesn't
require an active SNMP server to be available? (Since I don't have such a
beast to hand).

--
My get-up-and-go just got up and went.

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 29, 2017

From glebius@FreeBSD.org

On Fri, Apr 28, 2017 at 01​:29​:10AM -0700, Dave Mitchell via RT wrote​:
D> On Thu, Apr 27, 2017 at 01​:54​:14PM -0700, Gleb Smirnoff wrote​:
D> > There is a memory leak regression in perl 5.24.1, not present in
D> > perl 5.22.3. We managed to repropuce it in a small cyclic program
D> > that uses Net​::SNMP module. Note, that problem doesn't belong to
D> > the module, it is in the core. When script is run with perl 5.24,
D> > the perl process memory quickly grows. When script is run with
D> > perl 5.22 the perl process memory is constant. The same Net​::SNMP
D> > module is used in both scenarios.
D>
D> Is it possible for you to reduce this further to something that doesn't
D> require an active SNMP server to be available? (Since I don't have such a
D> beast to hand).

If you are testing on FreeBSD, then just launching bsnmpd is sufficient​:

# bsnmpd

If you are testing on Linux, installing net-snmp and launching it with
(I believe) default settings should be sufficient.

On my side I will try to reduce the test case, but can't promise
success.

--
Totus tuus, Glebius.

@p5pRT
Copy link
Author

p5pRT commented Apr 29, 2017

From @iabyn

On Fri, Apr 28, 2017 at 08​:32​:08AM -0700, Gleb Smirnoff wrote​:

If you are testing on Linux, installing net-snmp and launching it with
(I believe) default settings should be sufficient.

Well, I've go an SNMP server running now, but it doesn't recognise

  while (($toid = shift @​oid_keys)) {
  print "toid=$toid\n";
  $result = $session->get_table(-baseoid => $toid,
  -maxrepetitions => 1,);
  defined $result or die sprintf("ERROR​: get_table​: %s\n", $session->error());

gives

  toid=1.3.6.1.2.1.31.1.1.1.1
  ERROR​: get_table​: The requested table is empty or does not exist

snmpwalk gives the following. Any ideas what to change OID_IFx to?

$ snmpwalk -v 1 localhost -c public
SNMPv2-MIB​::sysDescr.0 = STRING​: Linux robin 4.4.14-200.fc22.x86_64 #1 SMP Fri Jun 24 21​:19​:33 UTC 2016 x86_64
SNMPv2-MIB​::sysObjectID.0 = OID​: NET-SNMP-MIB​::netSnmpAgentOIDs.10
ISMAN-EVENT-MIB​::sysUpTimeInstance = Timeticks​: (102346) 0​:17​:03.46
SNMPv2-MIB​::sysContact.0 = STRING​: Root <root@​localhost> (configure /etc/snmp/snmp.local.conf)
SNMPv2-MIB​::sysName.0 = STRING​: robin
SNMPv2-MIB​::sysLocation.0 = STRING​: Unknown (edit /etc/snmp/snmpd.conf)
SNMPv2-MIB​::sysORLastChange.0 = Timeticks​: (1) 0​:00​:00.01
SNMPv2-MIB​::sysORID.1 = OID​: SNMP-MPD-MIB​::snmpMPDCompliance
SNMPv2-MIB​::sysORID.2 = OID​: SNMP-USER-BASED-SM-MIB​::usmMIBCompliance
SNMPv2-MIB​::sysORID.3 = OID​: SNMP-FRAMEWORK-MIB​::snmpFrameworkMIBCompliance
SNMPv2-MIB​::sysORID.4 = OID​: SNMPv2-MIB​::snmpMIB
SNMPv2-MIB​::sysORID.5 = OID​: SNMP-VIEW-BASED-ACM-MIB​::vacmBasicGroup
SNMPv2-MIB​::sysORID.6 = OID​: TCP-MIB​::tcpMIB
SNMPv2-MIB​::sysORID.7 = OID​: IP-MIB​::ip
SNMPv2-MIB​::sysORID.8 = OID​: UDP-MIB​::udpMIB
SNMPv2-MIB​::sysORID.9 = OID​: SNMP-NOTIFICATION-MIB​::snmpNotifyFullCompliance
SNMPv2-MIB​::sysORID.10 = OID​: NOTIFICATION-LOG-MIB​::notificationLogMIB
SNMPv2-MIB​::sysORDescr.1 = STRING​: The MIB for Message Processing and Dispatching.
SNMPv2-MIB​::sysORDescr.2 = STRING​: The management information definitions for the SNMP User-based Security Model.
SNMPv2-MIB​::sysORDescr.3 = STRING​: The SNMP Management Architecture MIB.
SNMPv2-MIB​::sysORDescr.4 = STRING​: The MIB module for SNMPv2 entities
SNMPv2-MIB​::sysORDescr.5 = STRING​: View-based Access Control Model for SNMP.
SNMPv2-MIB​::sysORDescr.6 = STRING​: The MIB module for managing TCP implementations
SNMPv2-MIB​::sysORDescr.7 = STRING​: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB​::sysORDescr.8 = STRING​: The MIB module for managing UDP implementations
SNMPv2-MIB​::sysORDescr.9 = STRING​: The MIB modules for managing SNMP Notification, plus filtering.
SNMPv2-MIB​::sysORDescr.10 = STRING​: The MIB module for logging SNMP Notifications.
SNMPv2-MIB​::sysORUpTime.1 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.2 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.3 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.4 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.5 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.6 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.7 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.8 = Timeticks​: (0) 0​:00​:00.00
SNMPv2-MIB​::sysORUpTime.9 = Timeticks​: (1) 0​:00​:00.01
SNMPv2-MIB​::sysORUpTime.10 = Timeticks​: (1) 0​:00​:00.01
HOST-RESOURCES-MIB​::hrSystemUptime.0 = Timeticks​: (254774123) 29 days, 11​:42​:21.23
End of MIB

--
You're only as old as you look.

@p5pRT
Copy link
Author

p5pRT commented May 1, 2017

From glebius@FreeBSD.org

  Dave,

On Sat, Apr 29, 2017 at 01​:51​:15AM -0700, Dave Mitchell via RT wrote​:
D> On Fri, Apr 28, 2017 at 08​:32​:08AM -0700, Gleb Smirnoff wrote​:
D> > If you are testing on Linux, installing net-snmp and launching it with
D> > (I believe) default settings should be sufficient.
D>
D> Well, I've go an SNMP server running now, but it doesn't recognise
D>
D> while (($toid = shift @​oid_keys)) {
D> print "toid=$toid\n";
D> $result = $session->get_table(-baseoid => $toid,
D> -maxrepetitions => 1,);
D> defined $result or die sprintf("ERROR​: get_table​: %s\n", $session->error());
D>
D> gives
D>
D> toid=1.3.6.1.2.1.31.1.1.1.1
D> ERROR​: get_table​: The requested table is empty or does not exist
D>
D> snmpwalk gives the following. Any ideas what to change OID_IFx to?
D>
D>
D> $ snmpwalk -v 1 localhost -c public
D> SNMPv2-MIB​::sysDescr.0 = STRING​: Linux robin 4.4.14-200.fc22.x86_64 #1 SMP Fri Jun 24 21​:19​:33 UTC 2016 x86_64
D> SNMPv2-MIB​::sysObjectID.0 = OID​: NET-SNMP-MIB​::netSnmpAgentOIDs.10
D> ISMAN-EVENT-MIB​::sysUpTimeInstance = Timeticks​: (102346) 0​:17​:03.46
D> SNMPv2-MIB​::sysContact.0 = STRING​: Root <root@​localhost> (configure /etc/snmp/snmp.local.conf)
D> SNMPv2-MIB​::sysName.0 = STRING​: robin
D> SNMPv2-MIB​::sysLocation.0 = STRING​: Unknown (edit /etc/snmp/snmpd.conf)
D> SNMPv2-MIB​::sysORLastChange.0 = Timeticks​: (1) 0​:00​:00.01
D> SNMPv2-MIB​::sysORID.1 = OID​: SNMP-MPD-MIB​::snmpMPDCompliance
D> SNMPv2-MIB​::sysORID.2 = OID​: SNMP-USER-BASED-SM-MIB​::usmMIBCompliance
D> SNMPv2-MIB​::sysORID.3 = OID​: SNMP-FRAMEWORK-MIB​::snmpFrameworkMIBCompliance
D> SNMPv2-MIB​::sysORID.4 = OID​: SNMPv2-MIB​::snmpMIB
D> SNMPv2-MIB​::sysORID.5 = OID​: SNMP-VIEW-BASED-ACM-MIB​::vacmBasicGroup
D> SNMPv2-MIB​::sysORID.6 = OID​: TCP-MIB​::tcpMIB
D> SNMPv2-MIB​::sysORID.7 = OID​: IP-MIB​::ip
D> SNMPv2-MIB​::sysORID.8 = OID​: UDP-MIB​::udpMIB
D> SNMPv2-MIB​::sysORID.9 = OID​: SNMP-NOTIFICATION-MIB​::snmpNotifyFullCompliance
D> SNMPv2-MIB​::sysORID.10 = OID​: NOTIFICATION-LOG-MIB​::notificationLogMIB
D> SNMPv2-MIB​::sysORDescr.1 = STRING​: The MIB for Message Processing and Dispatching.
D> SNMPv2-MIB​::sysORDescr.2 = STRING​: The management information definitions for the SNMP User-based Security Model.
D> SNMPv2-MIB​::sysORDescr.3 = STRING​: The SNMP Management Architecture MIB.
D> SNMPv2-MIB​::sysORDescr.4 = STRING​: The MIB module for SNMPv2 entities
D> SNMPv2-MIB​::sysORDescr.5 = STRING​: View-based Access Control Model for SNMP.
D> SNMPv2-MIB​::sysORDescr.6 = STRING​: The MIB module for managing TCP implementations
D> SNMPv2-MIB​::sysORDescr.7 = STRING​: The MIB module for managing IP and ICMP implementations
D> SNMPv2-MIB​::sysORDescr.8 = STRING​: The MIB module for managing UDP implementations
D> SNMPv2-MIB​::sysORDescr.9 = STRING​: The MIB modules for managing SNMP Notification, plus filtering.
D> SNMPv2-MIB​::sysORDescr.10 = STRING​: The MIB module for logging SNMP Notifications.
D> SNMPv2-MIB​::sysORUpTime.1 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.2 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.3 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.4 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.5 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.6 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.7 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.8 = Timeticks​: (0) 0​:00​:00.00
D> SNMPv2-MIB​::sysORUpTime.9 = Timeticks​: (1) 0​:00​:00.01
D> SNMPv2-MIB​::sysORUpTime.10 = Timeticks​: (1) 0​:00​:00.01
D> HOST-RESOURCES-MIB​::hrSystemUptime.0 = Timeticks​: (254774123) 29 days, 11​:42​:21.23
D> End of MIB

Seems like you got snmpd in the default configuration. You need this in snmpd.conf​:

view almostEverything included .1
rocommunity public default -V almostEverything

It is probably already there, but commented out. Just add them and restart snmpd.

I have just checked with net-snmpd instead of FreeBSD in base snmpd. The script
works exactly the same.

--
Totus tuus, Glebius.

@p5pRT
Copy link
Author

p5pRT commented May 2, 2017

From @iabyn

On Mon, May 01, 2017 at 02​:02​:58PM -0700, Gleb Smirnoff wrote​:

Seems like you got snmpd in the default configuration. You need this in snmpd.conf​:

view almostEverything included .1
rocommunity public default -V almostEverything

Thanks, I can reproduce it now.

The leak was fixed in 5.25.10 by the following commit, but it hasn't
been back-ported to maint-5.24 yet​:

commit 1050723
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Wed Feb 15 15​:58​:24 2017 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Wed Feb 15 16​:08​:13 2017 +0000

  avoid a leak in list assign from/to magic values
 
  RT #130766
 
  A leak in list assignment was introduced by v5.23.6-89-gbeb08a1 and
  extended with v5.23.6-90-g5c1db56.
 
  Basically the code in S_aassign_copy_common() which does a mark-and-sweep
  looking for common vars by temporarily setting SVf_BREAK on LHS SVs then
  seeing if that flag was present on RHS vars, very temporarily removed that
  flag from the RHS SV while mortal copying it, then set it again. After
  those two commits, the "resetting" code could set SVf_BREAK on the RHS SV
  even when it hadn't been been present earlier.
 
  This meant that on exit from S_aassign_copy_common(), some SVs could be
  left with SVf_BREAK on. When that SV was freed, the SVf_BREAK flag meant
  that the SV head wasn't planted back in the arena (but PL_sv_count was
  still decremented). This could lead to slow growth of the SV HEAD arenas.
 
  The two circumstances that could trigger the leak were​:
 
  1) An SMG var on the LHS and a temporary on the RHS, e.g.
 
  use Tie​::Scalar;
  my ($s, $t);
  tie $s, 'Tie​::StdScalar'; # $s has set magic
  while (1) {
  ($s, $t) = ($t, map 1, 1, 2); # the map returns temporaries
  }
 
  2) A temporary on the RHS which has GMG, e.g.
 
  my $s = "abc";
  pos($s) = 1;
  local our ($x, $y);
  while (1) {
  my $pr = \pos($s); # creates a ref to a TEMP with get magic
  ($x, $y) = (1, $$pr);
  }
 
  Strictly speaking a TEMP isn't required for either case; just a situation
  where there's always a fresh SV on the RHS for each iteration that will
  soon get freed and thus leaked.
 
  This commit doesn't include any tests since I can't think of a way of
  testing it. svleak.t relies on PL_sv_count, which in this case doesn't
  show the leak.

--
This email is confidential, and now that you have read it you are legally
obliged to shoot yourself. Or shoot a lawyer, if you prefer. If you have
received this email in error, place it in its original wrapping and return
for a full refund. By opening this email, you accept that Elvis lives.

@p5pRT
Copy link
Author

p5pRT commented May 2, 2017

@iabyn - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented May 2, 2017

From glebius@FreeBSD.org

  Thanks a lot, Dave!

On Tue, May 02, 2017 at 04​:08​:22PM +0100, Dave Mitchell wrote​:
D> On Mon, May 01, 2017 at 02​:02​:58PM -0700, Gleb Smirnoff wrote​:
D> > Seems like you got snmpd in the default configuration. You need this in snmpd.conf​:
D> >
D> > view almostEverything included .1
D> > rocommunity public default -V almostEverything
D> >
D>
D> Thanks, I can reproduce it now.
D>
D> The leak was fixed in 5.25.10 by the following commit, but it hasn't
D> been back-ported to maint-5.24 yet​:
D>
D> commit 1050723
D> Author​: David Mitchell <davem@​iabyn.com>
D> AuthorDate​: Wed Feb 15 15​:58​:24 2017 +0000
D> Commit​: David Mitchell <davem@​iabyn.com>
D> CommitDate​: Wed Feb 15 16​:08​:13 2017 +0000
D>
D> avoid a leak in list assign from/to magic values
D>
D> RT #130766
D>
D> A leak in list assignment was introduced by v5.23.6-89-gbeb08a1 and
D> extended with v5.23.6-90-g5c1db56.
D>
D> Basically the code in S_aassign_copy_common() which does a mark-and-sweep
D> looking for common vars by temporarily setting SVf_BREAK on LHS SVs then
D> seeing if that flag was present on RHS vars, very temporarily removed that
D> flag from the RHS SV while mortal copying it, then set it again. After
D> those two commits, the "resetting" code could set SVf_BREAK on the RHS SV
D> even when it hadn't been been present earlier.
D>
D> This meant that on exit from S_aassign_copy_common(), some SVs could be
D> left with SVf_BREAK on. When that SV was freed, the SVf_BREAK flag meant
D> that the SV head wasn't planted back in the arena (but PL_sv_count was
D> still decremented). This could lead to slow growth of the SV HEAD arenas.
D>
D> The two circumstances that could trigger the leak were​:
D>
D> 1) An SMG var on the LHS and a temporary on the RHS, e.g.
D>
D> use Tie​::Scalar;
D> my ($s, $t);
D> tie $s, 'Tie​::StdScalar'; # $s has set magic
D> while (1) {
D> ($s, $t) = ($t, map 1, 1, 2); # the map returns temporaries
D> }
D>
D> 2) A temporary on the RHS which has GMG, e.g.
D>
D> my $s = "abc";
D> pos($s) = 1;
D> local our ($x, $y);
D> while (1) {
D> my $pr = \pos($s); # creates a ref to a TEMP with get magic
D> ($x, $y) = (1, $$pr);
D> }
D>
D> Strictly speaking a TEMP isn't required for either case; just a situation
D> where there's always a fresh SV on the RHS for each iteration that will
D> soon get freed and thus leaked.
D>
D> This commit doesn't include any tests since I can't think of a way of
D> testing it. svleak.t relies on PL_sv_count, which in this case doesn't
D> show the leak.
D>
D>
D> --
D> This email is confidential, and now that you have read it you are legally
D> obliged to shoot yourself. Or shoot a lawyer, if you prefer. If you have
D> received this email in error, place it in its original wrapping and return
D> for a full refund. By opening this email, you accept that Elvis lives.
D>

--
Totus tuus, Glebius.

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release today of Perl 5.26.0, this and 210 other issues have been
resolved.

Perl 5.26.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.26.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

@khwilliamson - Status changed from 'pending release' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant