eukreign / python-v8

Apache License 2.0
12 stars 6 forks source link

returning a javascript object containing a python object from a python function called from javascript causes a memory leak #18

Open eukreign opened 10 years ago

eukreign commented 10 years ago

From csaft...@gmail.com on July 18, 2013 15:53:57

What steps will reproduce the problem? Run the following code (also attached);

import gc import weakref

import PyV8

tracks = {} #map weakref id to (weakref, description) def trackeddeleted(r): , descr = tracks[id(r)] print ("Tracked object '%s' just deleted." % (descr,)) del tracks[id(r)] def track(o, descr): r = weakref.ref(o, tracked_deleted) tracks[id(r)] = (r, "%s:%s" % (o.class.name, descr)) return o

class EmptyProxy(object): pass

class Global(object): def init(self): pass

def track(self, obj, descr):
    return track(obj, descr)

def out(self, v):
    assert isinstance(v, str)        
    print "-- Script out: %s --" % (v,)

def returnArg(self, arg):
    return arg

def doNothing(self, arg):
    pass

def Empty(self):
    return EmptyProxy()

def run_case(name, js_setup, js_cleanup): print "Case '%s':" % (name,) ctxt = PyV8.JSContext(Global()) with ctxt: print " Runnning setup" ctxt.eval(js_setup)

    print "  Running cleanup"
    ctxt.eval(js_cleanup)
    print "  V8 gc"
    PyV8.JSEngine.collect()
    print "  Py gc"
    gc.collect()
    print "  V8 gc"
    PyV8.JSEngine.collect()
    print "  Py gc"
    gc.collect()
    print "  Py gc.garbage:", gc.garbage
print

gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS)

run_case("tracktest", """ var x = track(Empty(), "OK"); """, """x = null;""")

run_case("return js obj with py in it", """

var pyObj = track(Empty(), "yes GC cause returning py obj"); returnArg(pyObj);

var jsWithPy = {obj: track(Empty(), "yes GC cause returning py obj")}; returnArg(jsWithPy.obj);

var jsWithPy2 = {obj: track(Empty(), "no GC cause returning js obj with py obj in it")}; returnArg(jsWithPy2);

""", """ pyObj = null; jsWithPy = null; jsWithPy2 = null; """) What is the expected output? What do you see instead? The first case is just to show how my testing mechanism works:

Case 'tracktest': Runnning setup Running cleanup V8 gc Tracked object 'EmptyProxy:OK' just deleted. Py gc V8 gc Py gc Py gc.garbage: []

For the second case I would expect all 3 objects to be GCd:

Case 'return js obj with py in it': Runnning setup Running cleanup V8 gc Tracked object 'EmptyProxy:yes GC cause returning py obj' just deleted. Tracked object 'EmptyProxy:yes GC cause returning py obj' just deleted. Tracked object 'EmptyProxy:no GC cause returning js obj with py obj in it' just deleted. Py gc V8 gc Py gc Py gc.garbage: []

However, the "no GC cause returning js obj with py obj in it" is not freed. What version of the product are you using? On what operating system? PyV8 r443 with Python 2.6.6 on Windows 7 Please provide any additional information below. PyV8 has a lot of memory leak issues!

Original issue: http://code.google.com/p/pyv8/issues/detail?id=188