diff options
author | David Mitchell <davem@iabyn.com> | 2010-07-12 20:53:04 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2010-07-14 23:06:18 +0100 |
commit | 803f274831f937654d48f8cf0468521cbf8f5dff (patch) | |
tree | 297f701cf0a8ef3af29be3017402207f1fa62707 /cv.h | |
parent | 96bafef935f82644670a19c8ca57886c240cd969 (diff) | |
download | perl-803f274831f937654d48f8cf0468521cbf8f5dff.tar.gz |
protect CvGV weakref with backref
Each CV usually has a pointer, CvGV(cv), back to the GV that corresponds
to the CV's name (or to *foo::__ANON__ for anon CVs). This pointer wasn't
reference counted, to avoid loops. This could leave it dangling if the GV
is deleted.
We fix this by:
For named subs, adding backref magic to the GV, so that when the GV is
freed, it can trigger processing the CV's CvGV field. This processing
consists of: if it looks like the freeing of the GV is about to trigger
freeing of the CV too, set it to NULL; otherwise make it point to
*foo::__ANON__ (and set CvAONON(cv)).
For anon subs, make CvGV a strong reference, i.e. increment the refcnt of
*foo::__ANON__. This doesn't cause a loop, since in this case the
__ANON__ glob doesn't point to the CV. This also avoids dangling pointers
if someone does an explicit 'delete $foo::{__ANON__}'.
Note that there was already some partial protection for CvGV with
commit f1c32fec87699aee2eeb638f44135f21217d2127. This worked by
anonymising any corresponding CV when freeing a stash or stash entry.
This had two drawbacks. First it didn't fix CVs that were anonmous or that
weren't currently pointed to by the GV (e.g. after local *foo), and
second, it caused *all* CVs to get anonymised during cleanup, even the
ones that would have been deleted shortly afterwards anyway. This commit
effectively removes that former commit, while reusing a bit of the
actual anonymising code.
Diffstat (limited to 'cv.h')
-rw-r--r-- | cv.h | 5 |
1 files changed, 4 insertions, 1 deletions
@@ -70,7 +70,10 @@ Returns the stash of the CV. #define CVf_WEAKOUTSIDE 0x0010 /* CvOUTSIDE isn't ref counted */ #define CVf_CLONE 0x0020 /* anon CV uses external lexicals */ #define CVf_CLONED 0x0040 /* a clone of one of those */ -#define CVf_ANON 0x0080 /* CvGV() can't be trusted */ +#define CVf_ANON 0x0080 /* implies: CV is not pointed to by a GV, + CvGV is refcounted, and + points to an __ANON__ GV; + at compile time only, also implies sub {} */ #define CVf_UNIQUE 0x0100 /* sub is only called once (eg PL_main_cv, * require, eval). */ #define CVf_NODEBUG 0x0200 /* no DB::sub indirection for this CV |