It's not working as I hoped.
I'm seeing random crashes in v8 Locker class when I implement a JS thread
that does some work, then spawns itself just before calling pthread_exit().
On OSX, I see the thread get respawned 15 times and it works like it
should. The 16th time, segfault. I ran it under gdb and see this:
14020 test3 exiting 16
14020 test3 respawn 16
runner
a
b
c
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xfffffffffffffff8
[Switching to process 14020 thread 0x1923]
v8::internal::ExitFrame::GetStateForFramePointer (
fp=<value temporarily unavailable, due to optimizations>,
state=0x105080400) at ../src/frames.cc:556
556 ../src/frames.cc: No such file or directory.
in ../src/frames.cc
However, spawning 1000 threads in the main program still works.
The runner, a, b, c lines are printf() I put in the code to see where it's
dying.
The runner() function is a wrapper around entering v8 from a newly started
thread.
static void *runner(void *p) {
printf("runner\n");
ThreadInfo *t = (ThreadInfo *)p;
printf("a\n");
pthread_setspecific(tls_key, t);
printf("b\n");
pthread_detach(pthread_self());
{
printf("c\n");
Locker loc;
printf("d\n");
HandleScope scope;
printf("e\n");
Handle<Value>v = t->o->Get(String::New("runHandler"));
printf("f\n");
if (v.IsEmpty()) {
printf("g\n");
printf("No runHandler\n");
printf("h\n");
pthread_exit(NULL);
}
else if (!v->IsFunction()) {
printf("i\n");
printf("No runHandler (not a function)\n");
printf("j\n");
pthread_exit(NULL);
}
printf("k\n");
Handle<Function>func = Handle<Function>::Cast(v);
printf("l\n");
Handle<Value>av[1];
printf("m\n");
av[0] = t->o;
printf("n\n");
// TryCatch tryCatch;
printf("CALL\n");
v = func->Call(context->Global(), 1, av);
// if (v.IsEmpty()) {
// printf("Exception!");
// ReportException(&tryCatch);
// }
}
printf("exitx\n");
pthread_exit(NULL);
}
You can see it's getting a Locker, and dying in the HandleScope creation.
The JS code looks like this:
function test3a() {
log('test3a alive ' + this.threadId);
this.on('exit', function() {
log('test3a respawn ' + this.threadId);
new Thread(test3);
// while(1);
});
log('test3a sleeping ' + this.threadId);
// sleep(1);
log('test3a exiting ' + this.threadId);
}
function test3() {
log('test3 alive ' + this.threadId);
this.on('exit', function() {
log('test3 respawn ' + this.threadId);
new Thread(test3a);
// while (1);
});
log('test3 sleeping ' + this.threadId);
// sleep(1);
log('test3 exiting ' + this.threadId);
}
function main() {
// for (var i=0; i<1000; i++) {
// sleep(2);
// new Thread(test4);
// }
new Thread(test3);
while (1) sleep(1);
}
The pthread create function looks like this:
static JSVAL create(JSARGS args) {
ThreadInfo *t;
t = new ThreadInfo;
t->threadId = nextThreadId++;
t->o = Persistent<Object>::New(args[0]->ToObject());
{
Unlocker ul;
pthread_create(&t->t, NULL, runner, t);
}
return Integer::New(t->threadId);
}
(The source to runner posted above).
Also of note is if I throw an Error() from JS in a thread, it's caught, but
the TryCatch doesn't seem to have valid data.
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users