YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

Detecting VM lock-up
Hop
#1 Posted : Tuesday, February 6, 2018 10:44:36 PM(UTC)
Rank: Member

Groups: Registered
Joined: 1/19/2015(UTC)
Posts: 12
Location: UK

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
What is the best mechanism for detecting when a VM has locked up, that is to say, stuck in an infinite loop?

My application wakes any suspended VMs each frame and then releases the thread if it becomes idle (finished) or keeps it alive for the next frame if it becomes suspended.

I'd like to detect if one of the threads becomes stuck in an infinite loop (say while(true) { /*no suspend in here*/} and warn and/or destroy it. Is the sq_setdebughook the best way to do this, or is there a better way?
absence
#2 Posted : Sunday, February 18, 2018 1:24:40 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 124
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
IMHO there is no good way to do it.
You can try using the debughook and set the current time to a variable both each time you start a script and inside sq_resume, then check the time difference (which then will be the time since last call of one of the two, hence your timeout).
However, to actually STOP the script will be bit tedious, only ways are to either throw an exception (which could be coverd by try/catch instructions, unfortunately) or never return from the debughook - which probably will leave the VM in an inconsistent state you most probably cannot safely sq_close in all cases. Not 100% sure about that, it might happen to work aswell, but one thing's for sure: You will have to correct the stack (the C++ one!) if you intend to stop the script by not returning from the debug hook! Hence, that's going to be a PITA.


However, when the programmer enters sh*t, the application usually is going to dip in. I would stick to that and simply allow for infinite loops. Still, I don't know why you want to mitigate this, but it's your decision...

If urgendtly needed, I would do Squirrel in a separate thread and install another thread watching for it. When squirrel stalls (same detection like above) let the second thread terminate the first one the hard way. (Again, quite a PITA and platform depending).

Plus, you could manipulate Squirrel VMs Execute() to check a variable and perform a hard termination.

Sorry I can't come up with a perfect solution.
Hop
#3 Posted : Wednesday, March 21, 2018 11:16:26 AM(UTC)
Rank: Member

Groups: Registered
Joined: 1/19/2015(UTC)
Posts: 12
Location: UK

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Thanks for the help.

I'd like to keep it simple if possible.

Perhaps if there was a way to suspend the VM from within the debughook there could be a simple solution. The application could then suspend the VM and maybe add a key to the root table to indicate that the thread had timed out. Is it possible to call a native closure such as suspend from within the debug hook?
absence
#4 Posted : Monday, March 26, 2018 12:40:59 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 124
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
Hmmm... good call, I just was about putting this off when I got an idea (*lightbulb on*)

The Debug hook is called for each call, return or return from exception as well as by a special opcode created by the compiler for each line - hence from different places.
When the hook is called, basically you're somewehere in an infitinite loop of the VM (SQVM::Execute), wich will return only on an OP_RETURN (when it's unwinding to the very bottom) or a native closure call that just(!) called sq_suspend.

I can imagine you could manipulate the CallInfo vector (to be exact, the instruction pointer of its top element) to point to some prepared squirrel bytecode unwinding the stack, or -probably more easier- calling a native closure that suspends the vm. (causing SQVM::Execute to return after the debug hook returned and hence the next instruction is fetched, which would be that native call then).
As you need acces to the internal structures of the VM you will need to include sqvm.h.

Okay, thinking over this is doable and more easy than expected. You could even resume when needed by restoring the instruction pointer and calling sq_resume, or call sq_close. However, if this works you should also have some "atexit" function called (for the squirrel programmer to be able to have cleanup stuff called in that, for example freeing resources allocated in native closures). Also always remember you're messing with Squirrels' internal structures.


I will investigate on this topic a bit (needing an exit keyword or function anyways).

absence
#5 Posted : Monday, March 26, 2018 12:55:44 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 124
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
Oh, BTW, this deffo can't work properley when the compiler did not generate debug infos (OP_LINE).
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.262 seconds.