in reply to How to instrument a "fake" subroutine?

Can anyone explain why a calling code-ref to a "fake" sub causes this recursion?
Because it's just like a normal sub calling itself since the coderef is pointing to the sub that is currently being called.

A way around calling the fake sub would be to see if the coderef was pointing to an actual sub living in a symbol table somewhere

#!/usr/bin/perl -w use Fcntl qw(LOCK_EX); my $lock_ex_coderef= \&Fcntl::LOCK_EX;; # instrument LOCK_EX *Fcntl::LOCK_EX = sub { print "LOCK_EX called\n"; return &$lock_ex_coderef if defined &$lock_ex_coderef; }; # call LOCK_EX $_ = LOCK_EX;
This works because LOCK_EX (which is what $lock_ex_coderef points to) isn't defined at that point.

Another (albeit more hackish) way to see if a dummy sub is being called is to see if the coderef and the symbol table entry have the same reference value

use Fcntl qw(LOCK_EX); # define here so the &Fcntl::LOCK_EX can see it my $lock_ex_coderef; # instrument LOCK_EX *Fcntl::LOCK_EX = sub { print "LOCK_EX called\n"; return &$lock_ex_coderef unless $lock_ex_coderef eq *{$Fcntl::{LOCK_EX}}{CODE}; }; $lock_ex_coderef = \&Fcntl::LOCK_EX; # call LOCK_EX $_ = LOCK_EX;
This is very icky (it won't pass string any time soon ;-), but somewhat effective as it halts recursion by seeing that it would be calling itself. Also having written the code I learned that $lock_ex_coderef is merely pointing to an entry in the symbol table whereas &Fcntl::LOCK_EX is pointing to a coderef (which is why the $lock_ex_coderef assignment had to go after the &Fcntl::LOCK_EX assignment).
HTH

_________
broquaint

Replies are listed 'Best First'.
Re: Re: How to instrument a "fake" subroutine?
by samtregar (Abbot) on May 22, 2002 at 21:07 UTC
    Because it's just like a normal sub calling itself since the coderef is pointing to the sub that is currently being called.

    I don't think I follow. How does it work on non-fake subs then? By your reasoning wouldn't they also recurse? (They don't.)

    Unfortunately my actual situation in Devel::Profiler is complicated enough that neither of your solutions will apply directly. But they have given me some good ideas.

    Thanks,
    -sam

      I don't think I follow. How does it work on non-fake subs then?
      Hmm, I think we may have our wires crossed (that'll teach me for posting after 10pm ;-) My reasoning is that if your return is the call from a coderef that is pointing to the current coderef then of course it will recurse e.g
      my $f = \&foo; *foo = sub { print "in foo()\n"; return &$f; } foo(); __output__ in foo() in foo() ... and so on
      $f is just pointing to *main::foo{CODE} and since &foo is defined by the time it is called $f will then be pointing to a fully fledged sub and it recurses. Am I missing something?
      HTH

      _________
      broquaint

      update: changed sub foo to *foo = sub {}

        Oh. You were just pointing out the obvious then. I was asking why and you told me what. That's ok. The rest of your post was very helpful.

        -sam