This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author bup
Recipients bup, docs@python
Date 2018-06-09.16:50:20
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1528563020.57.0.592728768989.issue33814@psf.upfronthosting.co.za>
In-reply-to
Content
Sort of because I'm really not sure if it's working as intended or not. When I found this out today, I noticed that the documentation of `exec` has been updated since the last time I saw it, which is good, but it still leaves much to be desired. Specifically, I don't feel it does enough to explain the supposed justification for `exec`'s ability to very easily trigger a catastrophic memory leak someone unfamiliar with the code they're working on may never have the patience (if not time) to track down.. 

An illustration:

    import itertools
    import sys
    import weakref
    
    def noleak():
        
        def outer():
            from itertools import repeat as reeeee
            def f():
                return reeeee(1, 1)
            return f
        
        f = outer()
        c = sys.getrefcount(f)
        return c, weakref.ref(f), sys.getrefcount(itertools.repeat)

    def leaks():
        ns = {}
        co =  ('from itertools import repeat as reeeee\n'
               'def f(): return reeeee(1, 1)')
        pre = sys.getrefcount(ns)
        exec(co, ns)
        pos = sys.getrefcount(ns)
        return (pre, pos), weakref.ref(ns['f']), sys.getrefcount(itertools.repeat)

    for i in range(10):
        leaks()
    for i in range(10):
        noleak()

Perhaps I'm wrong in thinking that this is behaving as intended and it actually is a bug. Starting from builtin_exec_impl I got as far as _PyFrame_New_NoTrack before I threw up my hands and decided this is something for someone else. 

If `exec` with only a `globals` argument is indeed working as intended, I still think it's ridiculous that every item added to that dict has an "extra", non-obvious reference count that is impossible to vanquish of from within Python. I intuited leaving `locals` blank will do what usually happens when functions take optional arguments, and *usually* that is *not* the triggering of a "hidden" memory leak.


Perhaps the only solution here is to deprecate `exec` accepting `globals` and `locals` as optional arguments.
History
Date User Action Args
2018-06-09 16:50:20bupsetrecipients: + bup, docs@python
2018-06-09 16:50:20bupsetmessageid: <1528563020.57.0.592728768989.issue33814@psf.upfronthosting.co.za>
2018-06-09 16:50:20buplinkissue33814 messages
2018-06-09 16:50:20bupcreate