50752009 Posted February 23, 2016 Share Posted February 23, 2016 struct padSendData { int buttonPushedID; int controlMoveState; int controlTurnState; }; Repeat the call engine->runWorldFunction(Unigine::Variable("setPadControl"),Unigine::Variable(padp->buttonPushedID),Unigine::Variable(padp->controlMoveState), Unigine::Variable(padp->controlTurnState)); 10:19:54 Interpreter::runWaits(): depth of stack is not zero 10:19:54 World::update(): world update function return 0 10:22:51 D:\BuildAgent\work\cd5ab32b6eb0bda3\Unigine\source\engine\EngineInterpreter.h:74: Assertion: 'depth > 0 && "EngineInterpreterInstance::end(): stack underflow"' 10:23:26 Shutdown How to solve this problem? Link to comment
silent Posted February 23, 2016 Share Posted February 23, 2016 Hi, Could you please provide a minimal test scene for reproduction?Thanks! How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
50752009 Posted February 23, 2016 Author Share Posted February 23, 2016 Engine *engine; void runReceiveThread(void* lpparam) { while(true) { Sleep(10); engine->runWorldFunction(Unigine::Variable("Test"),Unigine::Variable(1),Unigine::Variable(2),Unigine::Variable(3)); } } int main(int argc,char **argv) { engine = Engine::init(UNIGINE_VERSION,argc,argv); _beginthread(runReceiveThread,0,0); // enter the main loop while(engine->isDone() == 0) { engine->update(); engine->render(); engine->swap(); } Engine::shutdown(); return 0; } Link to comment
shodan Posted February 25, 2016 Share Posted February 25, 2016 Hi, _beginthread(runReceiveThread,0,0); This is the root cause. You're accessing *engine object from a separate thread. That is currently unsafe in multiple ways. First, engine is not yet exactly thread-safe in general. That is, attempting to use it concurrently from different threads might cause pretty much any kind of unexpected behavior: crashes, freezes, data corruption, you name it. Second, the runWorldFunction() specifically is definitely not thread-safe. We might be able to fix this particular function as soon as the upcoming 2.2 release. (We can't guarantee that timeline though; there's some more analysis and testing to be done.) Third, and more importantly, even merely accessing the *engine object in this way is not thread-safe. Assume your thread wakes up while the engine is reinitialized, or being shut down, so that the *engine object is no longer valid, even though the pointer is still valid. Crash, boom, bang. At the very least, you should add a flag that the engine pointer is still alive. Or better yet, at least in versions 2.1 and before, you could protect all the engine accesses with a mutex, as follows: MyMutex g_engine_mutex; void MyThreadFunc() { g_engine_mutex.lock(); if (engine) engine->doThings(...); g_engine_mutex.unlock(); } void main() { ... // enter the main loop while(engine->isDone() == 0) { g_engine_mutex.lock(); engine->update(); g_engine_mutex.unlock(); g_engine_mutex.lock(); engine->render(); g_engine_mutex.unlock(); g_engine_mutex.lock(); engine->swap(); g_engine_mutex.unlock(); } g_engine_mutex.lock(); Engine::shutdown(); ... } Link to comment
Recommended Posts