#21 ✓resolved
marc

segfault/bus error in loop

Reported by marc | June 25th, 2009 @ 06:11 PM

hi,

i have the following problem. i want to build a serverside JS framework ontop of cherrypy. here is the code that freezes when executing:

#!/bin/env python

import spidermonkey

rt = spidermonkey.Runtime()

class Session(object):
    def __init__(self):
        self.asdf = 0
        
    def set(self, key):
        return key

def app():
    cx = rt.new_context()
    cx.add_global('session', Session)
    
    data = cx.execute('new session().set(Math.random());')
    return [str(data)]

for i in range(1, 1000):
    print app()

the code freezes between the 10 to 15th execution. Sometime it segfaults, somtimes it only freezes ans sometimes i get an "Bus Error".

i have to get a fresh context on every request in order to get rid of the old code, that has been executed before. moving new_context() and add_global() out of the function solves the problem but then i have no clean environment to work with. is there a way to recycle an existing context in order skip creating a new one?

i'm using the latest trunk version on mac os x 10.5 with python 2.6.

thanks in advance,

cheers marc

Comments and changes to this ticket

  • Paul J. Davis

    Paul J. Davis June 25th, 2009 @ 07:11 PM

    • Tag set to segfault, session-creation

    Marc,

    Interesting. I'll take a look tonight or tomorrowish when I get a chance. Off the top of my head there's no real good way to clean a context completely after use.

    There is another pattern that I've seen used to create a subcontext. This would basically be something along the lines of you create your context, add the Session global, and then use sub contexts on each request. I'm not sure how much that saves or even what the current issue is though, but it might be something I could add.

    I'll post more when after I peep some back traces.

  • Paul J. Davis

    Paul J. Davis June 25th, 2009 @ 11:32 PM

    • Tag changed from segfault, session-creation to segfault, session-creation, wtf

    Looking into this suggests a fairly non-trivial bug somewhere. It appears to be deterministic though, so at least there's that.

    Initial inspection shows things deadlocking in garbage collection when cycling through the test case. The traceback shows a deadlock in JS_BeginRequest from jsobject's finalize method. No matter what I do it just appears to move the deadlock or create a segfault. I did a bit of auditing on the begin/end requests and found a mismatch, but after fixing it appears unrelated.

    When trying to address the possibly maybe related causes I end up just pushing a repeatable error to different parts of the code. As a result, my hunch is that this is some sort of memory error. I'm a bit disadvantaged investigating at the moment, but maybe something will come to me in a bit. For the time being this is the main stack trace I'm getting when running:

    Program received signal SIGINT, Interrupt.
    0x9208e46e in __semwait_signal ()
    0  0x9208e46e in __semwait_signal ()
    1  0x920b93e6 in _pthread_cond_wait ()
    2  0x920b8dcd in pthread_cond_wait$UNIX2003 ()
    3  0x0156d921 in PR_WaitCondVar ()
    4  0x0143fe86 in JS_BeginRequest (cx=0x480f420) at jsapi.c:823
    5  0x0143eac5 in get_py_obj [inlined] () at pyobject.c:222
    6  0x0143eac5 in js_finalize (jscx=0x480f420, jsobj=0xca8fb8) at pyobject.c:223
    7  0x014a7a95 in js_DropObjectMap [inlined] () at jsobj.c:2750
    8  0x014a7a95 in js_FinalizeObject (cx=0x480f420, obj=0x480f420) at jsobj.c:2753
    9  0x01483bd6 in js_GC (cx=0x480f420, gckind=GC_NORMAL) at jsgc.c:3028
    10 0x01446e28 in JS_MaybeGC (cx=0x480f420) at jsapi.c:1873
    11 0x0143aaf0 in Context_execute (self=0x1417f00, args=0x4, kwargs=0x0) at context.c:589
    

    Calum, if you can run the ./go command in the root directory to check the top of your stack trace that'd be great. You'll need to add this test case to trigger:

    import t
    
    class Session(object):
        def __init__(self):
            self.asdf = 0
    
        def set(self, key):
           return key
    
    @t.rt()
    def test_turnover(rt):
        for i in range(1000):
            cx = rt.new_context()
            cx.add_global('session', Session)
            data = cx.execute('new session().set(Math.random());')
            t.ne(data, None)
    

    Other things of interest: Putting the 'cx = rt.new_context()' statement outside the loop alleviates the issue. Looking at the create/destroy methods I don't see anything obvious. Also, I run these tests in a single process with nosetests so its a bit odd that just running a couple creates in a tight loop is triggering this when running the tests normally doesn't.

    I am perplexed.

  • marc

    marc June 26th, 2009 @ 04:38 AM

    hi paul,

    thank for your effort to get into it and for investigating this strange behaviour.
    another funny thing is, that moving the

    rt = spidermonkey.Runtime()
    œœœ
    
    into the loop, results in a Bus Error after exactly 128 cycles.
    i'm sorry for just reporting this issue without directly submitting patches/solutions, but i'm not familar with c.
    
    thank you in advance.
    cheers from germany,
    
    marc
    
  • marc

    marc June 26th, 2009 @ 04:39 AM

    ouch...sorry, i've forgotten to close the code-block :)

  • Paul J. Davis

    Paul J. Davis June 26th, 2009 @ 07:46 PM

    • State changed from “new” to “resolved”

    (from [6d5e357f9cd4ae3cfaaf25aafbf6c121cf519ac2]) 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] http://github.com/davisp/python-spidermonkey/commit/6d5e357f9cd4ae3...

  • Paul J. Davis

    Paul J. Davis June 26th, 2009 @ 07:47 PM

    marc,

    Can you pull github and double check that the error is fixed for you?

    Paul

  • marc

    marc June 28th, 2009 @ 06:47 PM

    hi paul,

    okay i've tested it with the git version and it works like a charm. thank you for solving the problem so fast.

    cheers marc

  • Paul J. Davis

    Paul J. Davis June 28th, 2009 @ 07:24 PM

    marc,

    Cool. I'll version bump and push to PyPI

    Paul

  • Paul J. Davis

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Python/JavaScript bridge module, making use of Mozilla's spidermonkey JavaScript implementation. Allows implementation of JavaScript classes, objects and functions in Python, and evaluation and calling of JavaScript scripts and functions respectively. Borrows heavily from Claes Jacobssen's Javascript Perl module, in turn based on Mozilla's 'PerlConnect' Perl binding.

People watching this ticket

Attachments

Referenced by

Pages