Advertisement

Assert failed

Started by June 09, 2009 11:16 PM
7 comments, last by dxj19831029 15 years, 5 months ago
HI, I try to use the Windows fiber with Script Engine. The interface I called to execute script is ExecuteString. I create the context and pass into ExecuteString. Now, I use fiber to switch inside ExecuteString, and resume to it later. And I have a assertion on as_context.cpp, line 139. I believe it's something wrong with active context problem. Should I prepare the function on the context? and call context->execute(). Cheers.
Whenever a context is executing it adds itself to the stack of active contexts, and when the context stops executing (i.e. returns from the Execute function) it will pop itself from the stack.

There is one stack of active contexts for each thread, however fibers share the same stack of contexts so you need to be careful when using contexts from multiple fibers.

In your case I guess you have something like this:


 Fiber1              Fiber2   |   | Execute()   | SwitchFiber() ----->  |                       |                       |                    Execute()                       |   |  <------------ SwitchFiber()   | Execute() returns   | assert failure


To avoid the assert failure (or application crash in release mode) you need to make sure Fiber2 completes its own script execution before it switches back to Fiber1.

Alternatively you can suspend the script execution in Fiber1, so that it returns from the Execute() function, then switch to Fiber2. Later on when you come back to Fiber1 you can resume the script execution by calling Execute() again (without first calling Prepare()).

You may want to take a look at the Coroutine sample in the AngelScript SDK. The Concurrent sample may also have some useful ideas for you.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

 Fiber1              Fiber2   |   | Execute()   | SwitchFiber() ----->  |                       |                       |                    Execute()                       |   |  <------------ SwitchFiber()   | Execute() returns   | assert failure

Refer to your diagram.
The switchFiber() function can be called from script function or inside script function as following:

 Fiber1              Fiber2   |   | Execute()   | ScriptFunc()        | (inside it)     SwitchFiber() ->  |                       |                       |                    Execute()                       |   cont ScriotFunc() ------------ SwitchFiber()   | (return ScriptFunc)   | Execute() returns   | assert failure


When I call the context->Suspend(), it need to return from ScriptFunc, isn't it? Can I switch script engine context by myself? Any suggestion?


Quote: Original post by WitchLord
Whenever a context is executing it adds itself to the stack of active contexts, and when the context stops executing (i.e. returns from the Execute function) it will pop itself from the stack.

There is one stack of active contexts for each thread, however fibers share the same stack of contexts so you need to be careful when using contexts from multiple fibers.

In your case I guess you have something like this:


 Fiber1              Fiber2   |   | Execute()   | SwitchFiber() ----->  |                       |                       |                    Execute()                       |   |  <------------ SwitchFiber()   | Execute() returns   | assert failure


To avoid the assert failure (or application crash in release mode) you need to make sure Fiber2 completes its own script execution before it switches back to Fiber1.

Alternatively you can suspend the script execution in Fiber1, so that it returns from the Execute() function, then switch to Fiber2. Later on when you come back to Fiber1 you can resume the script execution by calling Execute() again (without first calling Prepare()).

You may want to take a look at the Coroutine sample in the AngelScript SDK. The Concurrent sample may also have some useful ideas for you.

Regards,
Andreas


I saw those two functions:
asPushActiveContext and asPopActiveContext.

Can I directly call them?

(Ps: From my understanding, I could do that:).)
By the way, it did not crash the application in the Release mode. I think that does make sense since the assertion checkpoint is gone, but we may have released context on the context manager stack. It does not matter, rite?

Cheers.

Quote: Original post by WitchLord
Whenever a context is executing it adds itself to the stack of active contexts, and when the context stops executing (i.e. returns from the Execute function) it will pop itself from the stack.

There is one stack of active contexts for each thread, however fibers share the same stack of contexts so you need to be careful when using contexts from multiple fibers.

In your case I guess you have something like this:


 Fiber1              Fiber2   |   | Execute()   | SwitchFiber() ----->  |                       |                       |                    Execute()                       |   |  <------------ SwitchFiber()   | Execute() returns   | assert failure


To avoid the assert failure (or application crash in release mode) you need to make sure Fiber2 completes its own script execution before it switches back to Fiber1.

Alternatively you can suspend the script execution in Fiber1, so that it returns from the Execute() function, then switch to Fiber2. Later on when you come back to Fiber1 you can resume the script execution by calling Execute() again (without first calling Prepare()).

You may want to take a look at the Coroutine sample in the AngelScript SDK. The Concurrent sample may also have some useful ideas for you.

Regards,
Andreas
asPushActiveContext and asPopActiveContext are not available for calling from the application. But why would you want to be able to call them anyway?

Correct, in release mode you won't hit the assert. But you will corrupt the stack of active contexts. That may lead to unforeseen behaviours, so you really do not want to do that. (In best cases you'll only get in trouble if you call asGetActiveContext)

I suggest you change the code to not call SwitchFiber directly from the script code. Instead implement it so that when the script wants to switch fibers it will call a function that sets a flag, and then suspends the context. When the context's Execute function returns, check this flag, and if it is set, then call SwitchFiber.

When the asIScriptContext::Suspend() is called, the virtual machine will halt the bytecode interpretation where it is, and return from the Execute() function so the application can continue it's normal flow. The next time Execute() is called the VM will resume the bytecode interpretation where it left off.

Why are you using fibers anyway? Are you just trying to implement co-routines for the scripts? Or do you need it for other application needs too? If you only need co-routines, then I suggest you do not use fibers at all, and instead use manual switching of script contexts. Please examine the 'co-routines' sample in the SDK for an implementation of that.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
I have already looked at the examples. :)

We use the fiber in our code as logic break point. We have the worker thread to do the time comsumed jobs. So, we will distribute time comsumed jobs to the workers, since it will take time, we have to wait until the worker return the results to us (usually it is internet request). At the same time, we do not want master thread to sleep. (Callback function solution is not valid option). Also we are not only use the script function call, we mix them togather.


So actually we can not make to use the script context switch as you suggested.

My question is: since we use switchFiber, it will keep all the stack values. Is that not enough for the scriptEngine?

will asPushActiveContext and asPopActiveContext destroy anything?
I want to use them to simulate the contextSwitch for the ScriptEngine. Can scriptEngine do script context switch at any point?

Cheers

Quote: Original post by WitchLord
asPushActiveContext and asPopActiveContext are not available for calling from the application. But why would you want to be able to call them anyway?

Correct, in release mode you won't hit the assert. But you will corrupt the stack of active contexts. That may lead to unforeseen behaviours, so you really do not want to do that. (In best cases you'll only get in trouble if you call asGetActiveContext)

I suggest you change the code to not call SwitchFiber directly from the script code. Instead implement it so that when the script wants to switch fibers it will call a function that sets a flag, and then suspends the context. When the context's Execute function returns, check this flag, and if it is set, then call SwitchFiber.

When the asIScriptContext::Suspend() is called, the virtual machine will halt the bytecode interpretation where it is, and return from the Execute() function so the application can continue it's normal flow. The next time Execute() is called the VM will resume the bytecode interpretation where it left off.

Why are you using fibers anyway? Are you just trying to implement co-routines for the scripts? Or do you need it for other application needs too? If you only need co-routines, then I suggest you do not use fibers at all, and instead use manual switching of script contexts. Please examine the 'co-routines' sample in the SDK for an implementation of that.


No, the asPopActiveContext won't destroy anything. As I mentioned before, the only problem that may occur is if you use asGetActiveContext anywhere, since it may return the wrong context pointer.

Doing a switch fiber within a function called from the script, should in theory not cause any problem. If the function call is not part of any expression in the script, then it should be perfectly safe. The script engine is designed so that it doesn't leave any loose references on the stack between statements.

I'll have to look into ways to support asGetActiveContext even with fiber switches in a future release.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Cool.

Thanks! I will try asPopActiveContext and push.

It may be good if you provide a interface to switch script context. :)

Anyway, Thanks for help

Cheers
Quote: Original post by WitchLord
No, the asPopActiveContext won't destroy anything. As I mentioned before, the only problem that may occur is if you use asGetActiveContext anywhere, since it may return the wrong context pointer.

Doing a switch fiber within a function called from the script, should in theory not cause any problem. If the function call is not part of any expression in the script, then it should be perfectly safe. The script engine is designed so that it doesn't leave any loose references on the stack between statements.

I'll have to look into ways to support asGetActiveContext even with fiber switches in a future release.


This topic is closed to new replies.

Advertisement