Anonymous avatar Anonymous committed 4ede337

Fix segfaults when large numbers of contexts.

Turns out that I had an error in my logic about how to reference count
the python context object. I removed references to it from Python
objects that are wrapped in the JavaScript VM. I'm more than 50% certain that
this is correct as when the Python context dies, it'll destroy the
JSContext* and along with it all references to Python objects that need
refernces to the Context.

[#21 state:resolved]

Comments (0)

Files changed (7)

 
 Richard Boulton
     * Initial patch for filtering Python access.
+
+marc
+    * Report on Context turnover causing segfaults.

spidermonkey/context.c

      *  garbage collection from happening on either side of the
      *  bridge.
      *
-     *  To make sure that the context stays alive we'll add a
-     *  reference to the Context* anytime we wrap a Python
-     *  object for use in JS.
-     *
      */
     JS_SetContextPrivate(self->cx, self);
 

spidermonkey/pyiter.c

     if(pycx == NULL)
     {
         fprintf(stderr, "*** NO PYTHON CONTEXT ***\n");
+        JS_EndRequest(jscx);
         return;
     }
 

spidermonkey/pyobject.c

     JS_EndRequest(jscx);
 
     Py_DECREF(pyobj);
-
-    // Technically, this could turn out to be nasty. If
-    // this is the last object keeping the python cx
-    // alive, then this call could be deleting the cx
-    // we're about to return to.
-    Py_DECREF(pycx);
 }
 
 PyObject*
         goto error;
     }
 
-    /*
-        As noted in Context_new, here we must ref the Python context
-        to make sure it stays alive while a Python object may be
-        referenced in the JS VM.
-    */
-    Py_INCREF(cx);
     ret = OBJECT_TO_JSVAL(jsobj);
     goto success;
 

spidermonkey/runtime.c

     if(self == NULL) goto error;
 
     self->rt = JS_NewRuntime(stacksize);
-    if(self->rt == NULL) goto error;
+    if(self->rt == NULL)
+    {
+        PyErr_SetString(JSError, "Failed to allocate new JSRuntime.");
+        goto error;
+    }
 
     goto success;
 
 error:
     Py_XDECREF(self);
+    self = NULL;
 
 success:
     return (PyObject*) self;

tests/test-context.py

     script = """
         var time = function() {return (new Date()).getTime();};
         var start = time();
-        while((time() - start) < 2000) {}
+        while((time() - start) < 100000) {}
     """
     cx.max_time(1)
     t.raises(SystemError, cx.execute, script)

tests/test-turnover.py

+# Copyright 2009 Paul J. Davis <paul.joseph.davis@gmail.com>
+#
+# This file is part of the python-spidermonkey package released
+# under the MIT license.
+import t
+
+#def test_churn_runtimes():
+#    for i in range(1000):
+#        rt = t.spidermonkey.Runtime()
+
+
+class Session(object):
+    def __init__(self):
+        self.key = None
+        
+    def set(self, key):
+        self.key = key
+        return self
+
+@t.rt()
+def test_churn_contexts(rt):
+    for i in range(1000):
+        cx = rt.new_context()
+        cx.add_global('session', Session)
+        data = cx.execute('new session().set("foo");')
+        t.eq(data.key, "foo")
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.