I want to embed V8 in my game engine, mainly because I prefer it's C++
API over that of SpiderMonkey's. However I'm having some thoughts
about thread-safety, since my engine would be executing each script in
its own thread.
I know that only a single thread can use V8 at a time, and that you
use the v8::Locker to lock access to V8 per-thread basis. This is all
good for me, because I can still unlock the thread if I have to wait
for some resource that is not related to V8. For sake of simplicity,
let's say I have to sleep for 2 seconds in a script, I could do this
by:
{
v8::Unlocker ul;
Sleep(2);
}
And while the thread sleeps, other scripts could still execute since
v8 is unlocked. However what I'm concerned about is how will
HandleScopes scope with this. Consider the following example:
{
v8::Locker l;
v8::HandleScope handle_scope;
{
v8::Unlocker ul;
Sleep(2);
}
v8::Local<v8::Value> str = v8::String::New("foobar");
// For sake of not having to write almost two identical functions,
// assume that ONLY thread 1 does this:
{
v8::Unlocker ul;
Sleep(2);
}
std::string s = String::AsciiValue ascii(str);
// And thread 2 would ONLY do this:
return;
}
Let's say that two threads run this same script. When the first thread
unlocks for the first time and goes to sleep, the 2nd thread will
create a new HandleScope, and thus all consecutive allocations are
done on the 2nd thread's handle scope. So when thread 2 goes to sleep,
and thread 1 wakes up, it'll create a new String using the HandleScope
that was created on the thread 2 while thread 1 was sleeping. Now
thread 1 will go to sleep again, and thread 2 will wake up. At this
point thread 2 simply returns, and since the HandleScope goes out of
scope, it'll free all the locals that it had allocated, _including_
the string created in thread 1 (since it was allocated using the wrong
HandleScope). After this the control returns back to the thread 1,
which tries to use the already de-allocated value, and probably crash
because of that.
Am I getting this right? If I am, is there any plausible way to get
around this, because I really need to be able to run multiple scripts
at the same time, but I have plenty of scripts that would block until
some sort of an event happens in the game, and other scripts need to
be able to run during the time the script waits.
Regards,
Reko Tiira
Or maybe just make a decision that no unlocks should be done while a
HandleScope is active in the script.
I want to embed V8 in my game engine, mainly because I prefer it's C++
API over that of SpiderMonkey's.
{
v8::Unlocker ul;
Sleep(2);
}
// For sake of not having to write almost two identical functions,
// assume that ONLY thread 1 does this:
{
v8::Unlocker ul;
Sleep(2);
}
std::string s = String::AsciiValue ascii(str);
Let's say that two threads run this same script. When the first thread
unlocks for the first time and goes to sleep, the 2nd thread will
create a new HandleScope, and thus all consecutive allocations are
done on the 2nd thread's handle scope.
So when thread 2 goes to sleep,
and thread 1 wakes up
, it'll create a new String using the HandleScope
that was created on the thread 2 while thread 1 was sleeping. Now
thread 1 will go to sleep again, and thread 2 will wake up. At this
point thread 2 simply returns, and since the HandleScope goes out of
scope, it'll free all the locals that it had allocated, _including_
the string created in thread 1 (since it was allocated using the wrong
HandleScope). After this the control returns back to the thread 1,
which tries to use the already de-allocated value, and probably crash
because of that.
Am I getting this right? If I am, is there any plausible way to get
around this, because I really need to be able to run multiple scripts
at the same time, but I have plenty of scripts that would block until
some sort of an event happens in the game, and other scripts need to
be able to run during the time the script waits.
Yeah I'm not doing that, the only thing that happens in this thread
during unlock is Sleep().
> > Let's say that two threads run this same script. When the first thread
> > unlocks for the first time and goes to sleep, the 2nd thread will
> > create a new HandleScope, and thus all consecutive allocations are
> > done on the 2nd thread's handle scope.
>
> Another tip: get rid of the HandleScopes. i've spent many hours
> experimenting and they cause me nothing but grief. Mysterious segfaults when
> a bound function returns? 9 times out of 10 it's caused by the mere
> existence of a HandleScope. i don't use them at all any more, and i can't
> see a functional difference (other than that my apps don't crash when the
> bound functions return, unless i've done something else illegal).
Thanks for the tip, I'll keep that in mind! I think that might be the
easiest solution. :)
> > So when thread 2 goes to sleep,
> > and thread 1 wakes up
>
> will GET A CHANCE to wake up. Other threads might contend.
Yeah, but for the sake of the example, let's just assume that there
are two threads.
> > , it'll create a new String using the HandleScope
> > that was created on the thread 2 while thread 1 was sleeping. Now
> > thread 1 will go to sleep again, and thread 2 will wake up. At this
> > point thread 2 simply returns, and since the HandleScope goes out of
> > scope, it'll free all the locals that it had allocated, _including_
> > the string created in thread 1 (since it was allocated using the wrong
> > HandleScope). After this the control returns back to the thread 1,
> > which tries to use the already de-allocated value, and probably crash
> > because of that.
>
> That sounds right to me (i say, without having actually run the code).
>
> Am I getting this right? If I am, is there any plausible way to get
>
> > around this, because I really need to be able to run multiple scripts
> > at the same time, but I have plenty of scripts that would block until
> > some sort of an event happens in the game, and other scripts need to
> > be able to run during the time the script waits.
>
> To me it looks like you're on the right track, but:
>
> - IMO you should not try to use a var created from Thread A over in Thread B
> - that just "sounds dangerous" to me. Maybe v8 does allow this, though.
Well the thing is that I don't really want to use a var created in
Thread A over in Thread B. The whole point of the example was that
while a thread is sleeping (and unlocked), some other thread might
create a HandleScope that will then "own" the variables created after
the thread wakes up, without the programmer really knowing about it.
The problem is with the fact that HandleScope's aren't really owned by
any thread, so when the control returns to the first thread, it'll
happily use the latest created HandleScope; even if it was created in
the other thread.
But I think I'll just do what you suggested, and don't use
HandleScopes at all. Thanks for the feedback!
Regards,
Reko Tiira
The whole point of the example was thatwhile a thread is sleeping (and unlocked), some other thread might
create a HandleScope that will then "own" the variables created after
the thread wakes up, without the programmer really knowing about it.
The problem is with the fact that HandleScope's aren't really owned by
any thread, so when the control returns to the first thread, it'll
happily use the latest created HandleScope; even if it was created in
the other thread.
But I think I'll just do what you suggested, and don't use
HandleScopes at all. Thanks for the feedback!
thread 1 will go to sleep again, and thread 2 will wake up. At this
point thread 2 simply returns, and since the HandleScope goes out of
scope, it'll free all the locals that it had allocated, _including_
the string created in thread 1 (since it was allocated using the wrong
HandleScope). After this the control returns back to the thread 1,
which tries to use the already de-allocated value, and probably crash
because of that.
Am I getting this right? If I am, is there any plausible way to get
around this, because I really need to be able to run multiple scripts
at the same time, but I have plenty of scripts that would block until
some sort of an event happens in the game, and other scripts need to
be able to run during the time the script waits.
Regards,
Reko Tiira
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
Regards,
Reko Tiira
On Apr 14, 10:33 am, Erik Corry <erik.co...@gmail.com> wrote:
That is a tip on the verge of FUD ;-) Can you be any more specific
about your problems? It sounds to me like you're accessing a Local
after the HandleScope in which it was created went away.
Matthias
That is a tip on the verge of FUD ;-) Can you be any more specificOn Tue, Apr 13, 2010 at 5:05 PM, Stephan Beal <sgb...@googlemail.com> wrote:
> Another tip: get rid of the HandleScopes. i've spent many hours
> experimenting and they cause me nothing but grief. Mysterious segfaults when
> a bound function returns? 9 times out of 10 it's caused by the mere
> existence of a HandleScope. i don't use them at all any more, and i can't
> see a functional difference (other than that my apps don't crash when the
> bound functions return, unless i've done something else illegal).
about your problems? It sounds to me like you're accessing a Local
after the HandleScope in which it was created went away.