JS Callback via OS callback

20 views
Skip to first unread message

klapa...@gmail.com

unread,
Apr 9, 2009, 8:31:55 PM4/9/09
to v8-users
Hi,

I'm trying to support up a simple timer going through OS service
(Win32 Timer queue).
The plan is to have a JS function called when timer expires/ticks.
OS provides the usual
void callback(void* userdata)

My void* is cast from/to Persistent <Function> which should be called.
Here's the payload function after casting the void* pointer

void DeferCallback(Persistent<Function>* timer)
{
HandleScope handle_scope; // if this is left out v8 bombs with
StackOverflow error
TryCatch try_catch;
Local<Value> result = timer->callback->Call(timer->callback, 0, 0);
// Quit system timer if function returns false or if an exception is
thrown
// My code in the OS static callback checks if timer has expired and
tells OS to quit calling if so.
if (result == False() || !try_catch.Exception().IsEmpty()) {
if (!try_catch.Exception().IsEmpty())
ReportException(&try_catch); // Defined in shell.cpp
timer->stop();
Persistent<Function> p(timer->callback);
p.Dispose();
}
}

This works for a while, then I get arbitrary crashes in V8 since
something tries to use some Handle value that is dead.

The script wrapper part is added to global thus:
// Defer object
Handle<ObjectTemplate> deferrer = ObjectTemplate::New();
deferrer->Set(String::New("once"), FunctionTemplate::New(DeferOnce),
DEFAULT_ATTR );
deferrer->Set(String::New("repeat"), FunctionTemplate::New
(DeferRepeat), DEFAULT_ATTR);

global->Set(String::New("Defer"), deferrer, DEFAULT_ATTR);

Defer doesn't use a constructor. User calls like
<js>
Defer.repeat(3, 1/10, myFunction);
</js>
to call myFunction 10 times per sec starting after 3 seconds.

This will work perfectly for a while, then crash.
The DeferRepeat function starts timer and forwards the function to
call:
Handle<Value> DeferRepeat(const Arguments& args)
{
HandleScope handle_scope;
// (arg checks elided)
// Get deferred function from arguments
Handle<Function> fun = Handle<Function>::Cast(args[2]);
Persistent<Function> func = Persistent<Function>::New(fun);

double waitsecs = args[0]->NumberValue();
double repeatsecs = args[1]->NumberValue();
// systemtimer() repeat(...) starts the OS service, with
DeferCallback as callback
Deferred* d = systemtimer()->repeat(waitsecs, repeatsecs,
DeferredCallPtr(&DeferCallback));
d->callback = func;
// where Deferred has a single member
// Persistent<Function> callback; -- which is the part used in
DeferCallback function above

return func;
}

I'm also unsure what I should send as Receiver when making the
function Call in DeferCallback:
Local<Value> result = timer->callback->Call(timer->callback, 0, 0);

Using the Function as its own receiver works, but I'm not sure if it
works right - just copied blindly from a post to this list...

Thanks for any tips,
k

Erik Corry

unread,
Apr 10, 2009, 3:55:24 AM4/10/09
to v8-u...@googlegroups.com
2009/4/10 <klapa...@gmail.com>:
Without having read your code I just wonder: Are you by any chance
calling V8 from more than one thread? See the comments around the
Locker class in include/v8.h for details of the rules for
multithreaded V8 programs.
--
Erik Corry, Software Engineer
Google Denmark ApS. CVR nr. 28 86 69 84
c/o Philip & Partners, 7 Vognmagergade, P.O. Box 2227, DK-1018
Copenhagen K, Denmark.

klapa...@gmail.com

unread,
Apr 10, 2009, 5:16:41 AM4/10/09
to v8-users
On 10 Apr, 09:55, Erik Corry <erik.co...@gmail.com> wrote:
> 2009/4/10  <klapaut...@gmail.com>:
> > This works for a while, then I get arbitrary crashes in V8 since
> > something tries to use some Handle value that is dead.
>
> Without having read your code I just wonder: Are you by any chance
> calling V8 from more than one thread?  See the comments around the
> Locker class in include/v8.h for details of the rules for
> multithreaded V8 programs.
>

Thanks for the heads-up, but my code is single-thread.
I'm running as extension of the shell example.

I'm more suspecting I'm leaving a Handle unmanaged that should be
Persistent, then the crash happens after it's garbage collected.
Some more debugging is on the agenda...

Ryan Dahl

unread,
Apr 10, 2009, 6:10:08 AM4/10/09
to v8-u...@googlegroups.com
Also a shot in the dark: Does the callback get executed as part of
the normal execution or is it like a signal handler? (I know nothing
about windows)

klapa...@gmail.com

unread,
Apr 10, 2009, 3:20:27 PM4/10/09
to v8-users

On 10 Apr, 11:16, klapaut...@gmail.com wrote:
> On 10 Apr, 09:55, Erik Corry <erik.co...@gmail.com> wrote:
>
> > 2009/4/10 <klapaut...@gmail.com>:
> > > This works for a while, then I get arbitrary crashes in V8 since
> > > something tries to use some Handle value that is dead.
>
> > Without having read your code I just wonder: Are you by any chance
> > calling V8 from more than one thread? See the comments around the
> > Locker class in include/v8.h for details of the rules for
> > multithreaded V8 programs.
>
> Thanks for the heads-up, but my code is single-thread.
> I'm running as extension of the shell example.

...or rather not. I retract and assert the opposite.
The thread in which the callback runs is not the same as main thread.

Time to look up how to run JS functions from different threads...

Thanks also to Ryan Dahl for this point,

k
Reply all
Reply to author
Forward
0 new messages