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

Can't undef active subroutine #18606

Closed
philiprbrenan opened this issue Feb 24, 2021 · 4 comments · Fixed by #21580
Closed

Can't undef active subroutine #18606

philiprbrenan opened this issue Feb 24, 2021 · 4 comments · Fixed by #21580

Comments

@philiprbrenan
Copy link

Should this produce: "deep recursion" not: "Can't undef active subroutine" ?

#!/usr/bin/perl
sub a
 {my sub b
   {&a; # Can't undef active subroutine
   }
  b
 }
a
@tonycoz
Copy link
Contributor

tonycoz commented Aug 16, 2021

I've reproduced this and I see what's happening.

Lexical subs have the SV* for their pad entry copied into the new pad (with an SvREFCNT_inc()), rather than a new SV being created, like other lexicals.

The leads to a more subtle problem too:

$ ./perl -le 'sub foo { my $x = shift; my sub b { $x }; foo(2) if $x == 1; return b() } print foo(1)'
2

Note that the outer b() (bound to where $x is 1) is called, but the inner recursive b() instance (where $x is 2) is used instead, for example with this non-lexical-sub equivalent:

$ ./perl -le 'sub foo { my $x = shift; my $b = sub { $x }; foo(2) if $x == 1; return $b->() } print foo(1)'
1

@jimav
Copy link

jimav commented Aug 24, 2023

Hi, Any thoughts about what to do about this?

If I understand, lexical subs can not currently be used with recursion which re-enters the scope where the lexical sub is defined, because the recursive call will not create a new closure (or not properly). Is that right?

If there is no solution possible, then it might be best to document the limitation in perlsub.

#!/usr/bin/env perl
use strict; use warnings; use feature qw/say state/;
STDOUT->autoflush; STDERR->autoflush;
say "Perl version $^V";

sub process($;$) {
  my ($value, $callback) = @_;
  say "### process($value,", ($callback//"undef"), ")";

  my sub inner {
    if ($callback) {
      return $callback->($value+1);
    } else {
      return $value+1;
    }
  }

  inner();
}

my $result =
  process(1, sub{
                 my $arg = shift;
                 say "#   callback called with arg $arg";
                 process($arg+100);
              });
say "result=", ($result//"undef");

#  Perl version v5.36.0
#  ### process(1,CODE(0x555555971f10))
#  #   callback called with arg 2
#  Can't undef active subroutine at /tmp/t line 25.

@tonycoz
Copy link
Contributor

tonycoz commented Aug 24, 2023

I'll take another look, I suspect now I was trying to solve some non-existent problems last time I tried to fix this.

tonycoz added a commit to tonycoz/perl5 that referenced this issue Aug 24, 2023
This previously put the same CV into the inner pad, so on a
recursive call into the owning sub, from this sub, this CV would
still be active, and the attempt to clone into the still busy CV
would throw.

Fixes Perl#18606 but definitely needs more tests.
jimav added a commit to jimav/ODF-lpOD_Helper that referenced this issue Sep 2, 2023
@jkeenan
Copy link
Contributor

jkeenan commented Oct 21, 2023

I'll take another look, I suspect now I was trying to solve some non-existent problems last time I tried to fix this.

@tonycoz, have you been able to look into this problem any further?

tonycoz added a commit to tonycoz/perl5 that referenced this issue Oct 22, 2023
This previously put the same CV into the inner pad, so on a
recursive call into the owning sub, from this sub, this CV would
still be active, and the attempt to clone into the still busy CV
would throw.

Fixes Perl#18606
tonycoz added a commit to tonycoz/perl5 that referenced this issue Oct 22, 2023
This previously put the same CV into the inner pad, so on a
recursive call into the owning sub, from this sub, this CV would
still be active, and the attempt to clone into the still busy CV
would throw.

Fixes Perl#18606
tonycoz added a commit to tonycoz/perl5 that referenced this issue Feb 11, 2024
This previously put the same CV into the inner pad, so on a
recursive call into the owning sub, from this sub, this CV would
still be active, and the attempt to clone into the still busy CV
would throw an error.

Fixes Perl#18606
tonycoz added a commit that referenced this issue Feb 20, 2024
This previously put the same CV into the inner pad, so on a
recursive call into the owning sub, from this sub, this CV would
still be active, and the attempt to clone into the still busy CV
would throw an error.

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

Successfully merging a pull request may close this issue.

4 participants