summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-08-14 19:16:14 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-08-15 06:20:19 -0700
commitf79aa60b66082c8bff80f325979742bfb6c73709 (patch)
tree9abac236ef8e21df8d6080190f3e12e2aae9eadd /pp.c
parent186abd568524c217f6dbd29891eef21c3cd2a3b0 (diff)
downloadperl-f79aa60b66082c8bff80f325979742bfb6c73709.tar.gz
Make lock(&foo) syntax nominally lock the subroutine
In 5.10, lock(&foo) was an error for non-lvalue subs. For lvalue subs, it passed &foo to the lockhook and return \&foo. In 5.12, lock(&foo) was still an error for non-lvalue subs. For lvalue subs, it would pass &foo to the lockhook and then either trip an assertion (-DDEBUGGING) or return &foo, resulting in inter- esting bugs. Commit f4df43b5e changed lock(&lvalue_sub) to call the sub and lock its return value. As Reini Urban pointed out in <CAHiT=DE5cVZbuCR3kb=Q5oCa18vo3jr5jZKmURHYha2PwF4pEQ@mail.gmail.com>, locking a subroutine does have its uses. Since lock(&foo) has never really worked anyway, we can still change this. So, for lvalue subs, this reverts back to the 5.10 behaviour. For non-lvalue subs, it now behaves the same way, the lvalue flag making no difference. Note that it still causes an error at run-time, if threads::shared is loaded, as its lockhook is conservative in what it accepts. But this change allows for future extensibility, unlike f4df43b5e. A note about the implementation: There are two pieces of code (at least) in op.c that convert an entersub op into an rv2cv, one in S_doref and the other in Perl_op_lvalue_flags. Originally (before f4df43b5e) it was S_doref that took care of that for OP_LOCK. But Perl_op_lvalue_flags is called first, so it would assume it was an assignment to a sub call and croak if there was no lvalue sub in the symbol table. This commit adds back the special case for OP_LOCK, but in Perl_op_lvalue_flags, not S_doref.
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/pp.c b/pp.c
index ca94935c30..3421d9701d 100644
--- a/pp.c
+++ b/pp.c
@@ -5914,9 +5914,9 @@ PP(pp_lock)
dSP;
dTOPss;
SV *retsv = sv;
- assert(SvTYPE(retsv) != SVt_PVCV);
SvLOCK(sv);
- if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV) {
+ if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV
+ || SvTYPE(retsv) == SVt_PVCV) {
retsv = refto(retsv);
}
SETs(retsv);