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

recommended 'my sub' example in perlsub leaks memory #15470

Closed
p5pRT opened this issue Jul 23, 2016 · 7 comments
Closed

recommended 'my sub' example in perlsub leaks memory #15470

p5pRT opened this issue Jul 23, 2016 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 23, 2016

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

Searchable as RT128708$

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2016

From @mauke

Created by @mauke

perldoc perlsub​:

| To use a lexical subroutine from inside the subroutine itself, you must
| predeclare it. The "sub foo {...}" subroutine definition syntax respects
| any previous "my sub;" or "state sub;" declaration.
|
| my sub baz; # predeclaration
| sub baz { # define the "my" sub
| baz(); # recursive call
| }

This example leaks memory, just like

  my $baz;
  $baz = sub { $baz->(); };

($baz keeps the sub alive, the sub keeps $baz alive).

It would be really good if recursive lexical subs could be made to not leak
memory.

Alternatively, this example should be removed from the documentation and
replaced by a warning that doing this kind of thing leads to memory leaks.

Perl Info

Flags:
    category=docs
    severity=low

Site configuration information for perl 5.24.0:

Configured by mauke at Mon May  9 21:21:33 CEST 2016.

Summary of my perl5 (revision 5 version 24 subversion 0) configuration:
   
  Platform:
    osname=linux, osvers=4.4.5-1-arch, archname=i686-linux
    uname='linux simplicio 4.4.5-1-arch #1 smp preempt thu mar 10 07:54:30 cet 2016 i686 gnulinux '
    config_args=''
    hint=previous, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -flto',
    cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion='', gccversion='6.1.1 20160501', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234, doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12, longdblkind=3
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-fstack-protector-strong -L/usr/local/lib -flto'
    libpth=/usr/local/lib /usr/lib/gcc/i686-pc-linux-gnu/6.1.1/include-fixed /usr/lib /lib /usr/local/lib /usr/lib/gcc/i686-pc-linux-gnu/6.1.1/include-fixed /usr/lib
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.23.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.23'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -flto -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.24.0:
    /home/mauke/usr/lib/perl5/site_perl/5.24.0/i686-linux
    /home/mauke/usr/lib/perl5/site_perl/5.24.0
    /home/mauke/usr/lib/perl5/5.24.0/i686-linux
    /home/mauke/usr/lib/perl5/5.24.0
    .


Environment for perl 5.24.0:
    HOME=/home/mauke
    LANG=en_US.UTF-8
    LANGUAGE=en_US
    LC_COLLATE=C
    LC_MONETARY=de_DE.UTF-8
    LC_TIME=de_DE.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/mauke/perl5/perlbrew/bin:/home/mauke/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
    PERLBREW_BASHRC_VERSION=0.73
    PERLBREW_HOME=/home/mauke/.perlbrew
    PERLBREW_ROOT=/home/mauke/perl5/perlbrew
    PERL_BADLANG (unset)
    PERL_UNICODE=SAL
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jul 27, 2016

From @cpansprout

On Sat Jul 23 15​:11​:40 2016, mauke- wrote​:

This is a bug report for perl from l.mai@​web.de,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------
[Please describe your issue here]

perldoc perlsub​:

| To use a lexical subroutine from inside the subroutine itself, you
must
| predeclare it. The "sub foo {...}" subroutine definition syntax
respects
| any previous "my sub;" or "state sub;" declaration.
|
| my sub baz; # predeclaration
| sub baz { # define the "my" sub
| baz(); # recursive call
| }

This example leaks memory, just like

my $baz;
$baz = sub { $baz->(); };

($baz keeps the sub alive, the sub keeps $baz alive).

It would be really good if recursive lexical subs could be made to not
leak
memory.

It cannot be fixed in general, because if you have two subs referencing each other in their pads--

  my sub foo;
  my sub bar;
  sub foo { bar if $whatever }
  sub bar { foo if $whatever }

--then you cannot know which pointer to weaken, since you cannot tell which sub will be referenced by user code last.

It might be possible to add a special case to break the reference loop of a self-referential sub. But there is no standard for storing a weak pointer in a pad (except the format hack). It’s not clear where to store the flag marking the pointer as weak.

Now, there is a hack for storing weak pointers to formats in pads (which are stored there solely for the sake of fixing up CvOUTSIDE pointers if they are defined within predeclared subs) consists of storing a weak RV which points to the format.

If we apply that to lexical subs, then padcv will have to have an extra special case to check for an RV. Is it worth the added complexity for something that is only a partial fix? If we need to educate users anyway, do we need a special case?

Alternatively, this example should be removed from the documentation

Or replaced with a state sub example. state subs will also leak, but no more than

sub AUTOLOAD { our $AUTOLOAD }

and
replaced by a warning that doing this kind of thing leads to memory
leaks.

Good idea.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jul 27, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2017

From zefram@fysh.org

The documentation was changed in the suggested way in commit
67bf5a3 in 5.27.3. This ticket can
be closed.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2017

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

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

From @khwilliamson

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

With the release yesterday of Perl 5.28.0, this and 185 other issues have been
resolved.

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

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

@p5pRT p5pRT closed this as completed Jun 23, 2018
@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

@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