Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Issues with Multi-threading?

25 views
Skip to first unread message

Paul Barnetta

unread,
Feb 16, 2009, 3:15:24 AM2/16/09
to dev-tech-...@lists.mozilla.org
Hi there,

I was after some help with another multi-threading issue I seem to have.
I raised bug 478336 about this last week but there's yet to be any
comment there so thought I'd ask here in the meantime.

I've tried reducing the problem down to another simple test case (which
looks pretty similar to my last one).. main spawns a bunch of threads
and waits for them to finish. The threads simply create and then destroy
a context each. I've tried adding a global object to each context (as
would normally be the case in a real program) before immediately
destroying the context but it doesn't seem to affect the results -- my
problem being that assertions are printed and the program aborts.

If I compile/run the application against the 1.7.0 release linked to on
the SpiderMonkey site I can run it thousands of times without any crash.
That leads me to believe there's no issue with the code per se -- but
naturally one of the reasons for including it here is to get some
comments in case there is an issue!

If I run the application against the tip of the TraceMonkey Mercurial
repository it works fine so long as I never let the number of contexts
dip to zero (ie, if I uncomment the commented lines in the file), but
will error more often than not on the box I'm testing with if I run the
program as-is:
$ for ITER in $(seq 100); do ./a.out 2>&1; done | sort | uniq -c
4 Assertion failure: first, at ../jscntxt.cpp:314
69 Assertion failure: rt->state == JSRTS_UP || rt->state ==
JSRTS_LAUNCHING, at ../jscntxt.cpp:465
The latter assertion made it in to the title of the bug I raised (it
seems rt->state == JSRTS_LANDING when the assertion fails).

Digging further it seems the behaviour changed (for the better?) around
revision 24662 which was when the patch for bug 477021 was committed. If
I update my checked-out copy of the TraceMonkey repository to revision
24661 I get SEGVs regardless of whether or not I let the number of
contexts fall to zero. They happen pretty regularly too:

$ while true; do echo -n .; ./a.out ; done
..Segmentation fault
...Segmentation fault
.....Segmentation fault
...Segmentation fault
.....Segmentation fault
..Segmentation fault
........Segmentation fault
.Segmentation fault

The fault also always happens at the same place:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7284b90 (LWP 27991)]
0xb7dacd40 in js_TraceContext (trc=0xb72842b0, acx=0x80ab888) at
../jsgc.cpp:2978
2978 FREE_OLD_ARENAS(acx->stackPool);
Current language: auto; currently c++
(gdb) bt
#0 0xb7dacd40 in js_TraceContext (trc=0xb72842b0, acx=0x80ab888) at
../jsgc.cpp:2978
#1 0xb7dad4b1 in js_TraceRuntime (trc=0xb72842b0, allAtoms=0) at
../jsgc.cpp:3115
#2 0xb7dadde1 in js_GC (cx=0x8092fd8, gckind=GC_NORMAL) at ../jsgc.cpp:3515
#3 0xb7d7be18 in js_DestroyContext (cx=0x8092fd8, mode=JSDCM_FORCE_GC)
at ../jscntxt.cpp:513
#4 0xb7d625fd in JS_DestroyContext (cx=0x8092fd8) at ../jsapi.cpp:1082
#5 0x080486fe in testfunc (ignored=0x0) at test.c:34
#6 0xb7beb1a2 in start_thread () from /lib/libpthread.so.0
#7 0xb7cc120e in clone () from /lib/libc.so.6

If I then update to revision 24662 and recompile I get the same results
as running from the tip -- ie, I cannot reproduce a crash at all if I
don't let the number of contexts dip to zero and I get plenty of crashes
if I do let the number dip to zero:

$ for ITER in $(seq 100); do ./a.out 2>&1; done | sort | uniq -c
4 Assertion failure: first, at ../jscntxt.cpp:284
71 Assertion failure: rt->state == JSRTS_UP || rt->state ==
JSRTS_LAUNCHING, at ../jscntxt.cpp:435

If I run the same program on one core (using taskset) I never see a crash.

So, is there a problem with my test case? Or is there another race
condition when the number of contexts transition between zero and non-zero?

I'd welcome any feedback, questions or the results from testing the
program on someone else's box.

Thanks in advance,
Paul

8<----


#include <stdlib.h>
#include <pthread.h>

#include "jsapi.h"

#define THREADS 100

static JSRuntime *rt;

static void * testfunc(void *ignored) {

JSContext *cx = JS_NewContext(rt, 0x1000);
if (cx) {
JS_BeginRequest(cx);
JS_DestroyContext(cx);
}

return NULL;
}

int main(void) {

rt = JS_NewRuntime(0x100000);
if (rt == NULL)
return 1;

/* Uncommenting this to guarantee there's always at least
* one context in the runtime prevents any crashes when
* running against revisions 24662 and later. */
// JSContext *cx = JS_NewContext(rt, 0x1000);

int i;
pthread_t thread[THREADS];
for (i = 0; i < THREADS; i++) {
if (pthread_create(&thread[i], NULL, testfunc, NULL))
return 1;
}

for (i = 0; i < THREADS; i++) {
if (pthread_join(thread[i], NULL))
return 1;
}

// JS_DestroyContext(cx);

JS_DestroyRuntime(rt);
JS_ShutDown();

return 0;
}

0 new messages