Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • pypy pypy
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 707
    • Issues 707
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 15
    • Merge requests 15
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
    • Model experiments
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar

Admin message

This instance will be upgraded to Heptapod 0.40.0 (final) on 2023-12-05 at 16:00 UTC+1

  • PyPyPyPy
  • pypypypy
  • Issues
  • #2030
Closed
Open
Issue created Apr 14, 2015 by Bitbucket Importer@bitbucket_importerMaintainer

Circular weakref callbacks never called (self._x = weakref.ref(self, callback))

Created originally on Bitbucket by jamadden (Jason Madden)

It appears that if an object holds a weak reference to itself, the callback for that reference is never called. It's as if when both the object and the reference to it become garbage at the same time, the callback isn't called.

I ran into this testing ZODB under PyPy (it used this pattern in ZODB.blob.Blob).

Here's an example of what happens under CPython:

$ /opt/local/bin/python2.7
Python 2.7.9 (default, Dec 13 2014, 15:13:49)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import weakref, sys
>>> class X(object):
...     pass
...
>>> x = X()
>>> x._ref = weakref.ref(x, lambda r: sys.stderr.write('callback\n'))
>>> del x
callback
>>>

Now, under PyPy (both 2.5.1 and a relatively recent nightly), the callback doesn't get called when the reference is deleted (but we expect that):

$ pypy
Python 2.7.9 (9c4588d731b7, Mar 23 2015, 16:20:40)
[PyPy 2.5.1 with GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>> import weakref, sys
>>>> class X(object):
....     pass
....
>>>> x = X()
>>>> x._ref = weakref.ref(x, lambda r: sys.stderr.write('callback\n'))
>>>> del x
>>>>

No problem, we need to ask GC to do a collection. We've seen this before.

>>>> import gc
>>>> gc.collect()
0

Hmm, maybe a few collections?

>>>> for _ in range(100): _ = gc.collect()
>>>>

Nothing.

If we use a separate reference object with a different lifetime, then it is called immediately after the first GC:

>>>> x = X()
>>>> ref = weakref.ref(x, lambda r: sys.stderr.write('direct callback\n'))
>>>> del x
>>>> gc.collect()
direct callback
0
>>>>
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking