Advertisement

User data

Started by October 26, 2008 11:25 AM
25 comments, last by SiCrane 16 years, 1 month ago
From what I can see, the call stack looks normal.

Your ScriptEngine wrapper is calling Release on asIScriptEngine, which deletes the asCModule it holds. The asCModule obviously has at least one global variable of a script class that is released. The script class has a declared destructor, which is called by creating a script context. As the context is executed it tries to push itself on the stack of active contexts, where each thread has its own stack.

The thread manager is a global variable outside of the engine, and has its own critical section. So the critical section should still exist at this time.

Unless..

Is your ScriptEngine wrapper instance a global variable? If it is, then as the application cleans up the global variables it may actually decide to clean up the thread manager before it cleans up your ScriptEngine wrapper instance, thus causing this crash upon exit.

This would explain why I never managed to recreate this scenario. In all my tests I never used a script engine wrapper, and especially not in a global variable.

I'll have to change the code to dynamically allocate the thread manager as the engine is created. This way I can make sure the thread manager is destroyed after the engine has done all its cleanup.

I'll make some new tests based on this information. Many thanks for showing the call stack, it was very valuable.

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

I recreated the problem with the following test:

// This test is to make sure it is possible to store the script engine in a global variable // that will be cleaned up only upon application exit. Previously this could cause the // application to crash when the library was built with multithreading, as the thread// manager was destroyed before the engine could clean up the global variables in the modules it held.#include "utils.h"namespace TestThreadMgr{// Compile a script that stores a global variable of a script class that has a destructor.// This will cause the destructor of the class to be called when the module is destroyed.static const char *script = "class MyTest             \n""{                        \n""   MyTest() {var = 1;}   \n""   ~MyTest() {var = 0;}  \n""   int var;              \n""}                        \n""MyTest global;           \n";// Here's our global variable that will release the engine upon application exitclass EngineWrapper{public:	EngineWrapper() { engine = 0; }	~EngineWrapper() { if( engine ) engine->Release(); }	asIScriptEngine *engine;} g_engine;bool Test(){	bool fail = false; 	g_engine.engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	COutStream out;	g_engine.engine->SetMessageCallback(asMETHOD(COutStream,Callback),&out,asCALL_THISCALL);	g_engine.engine->AddScriptSection(0, "script", script, strlen(script), 0);	g_engine.engine->Build(0);	g_engine.engine->ClearMessageCallback();	// Now the bomb has been armed. When the test application exits, if all goes 	// well the bomb should be disarmed correctly without crashing the application.	// Success	return fail;}} // namespace


Now, I'll provide the fix. Thanks a lot.

[edit]The fix is now ready and tested successfully. Hopefully I'll be able to check in the code tonight.[/edit]

[edit]I've checked in the fix now.[/edit]

[Edited by - WitchLord on October 29, 2008 6:45:30 PM]

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
It's not actually a global, though it probably looks a lot like one to AngelScript. The engine pointer is held in a managed object that gets cleaned up during garbage collection. Either way the fix seems to work.

And I think with that my basic AngelScript debugger is finished for all the features that I had planned. I've re-uploaded the project in case you're interested in seeing it. Thanks for all the help.
So, what's the verdict? How well does AngelScript work with C#?

I know very little of C#, so I'm curious how the interaction between AngelScript and the C# application worked out.

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

Usability wise it's a little easier than using AngelScript in C++ with AS_MAX_PORTABILITY. To interface with AS you need to write out all the generic methods, but since delegates can can contain state you don't need to do any tricks like associating data with function ids. Plus having a type safe layer means less looking up if a void * is actually an object * or object **. On the downside I can't do any of the preprocessor or template tricks that I could in C++ to speed up binding. Though there might be some stuff with runtime code generation I could try to make up for it.

The weird thing from the C# side is that both C# value and reference types will behave like C# reference types in the scripts. Basically, I bound a special kind of smart pointer than can hold objects in the managed heap as a value type in the script engine. So to AS they look like value types; you don't need to deal with handles. But copying and assigning these objects will behave like C# references. I don't know if it would be an issue in practice. Being the one who implemented it, I obviously know what to expect to happen.

On the whole, I'm pretty happy with the result.
Thanks for the information.

I had the impression that .NET would have a lot of gotcha's that would make it more difficult to use AngelScript with it. But I'm very happy to see it isn't so. With this affirmation I can add .NET as another supported platform to the features of AngelScript.

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
Well maybe once 2.15 comes out; I still need SetUserData(), GetUserData() and GetGlobalVarTypeId() for my implementation. :)

This topic is closed to new replies.

Advertisement