🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Odd crash with LUA

Started by
3 comments, last by Monder 20 years ago
In my script system for every script that is loaded a new state is created. When you run a function in that script a new thread is created from the script's main state and the function run in that thread, this is so I can have c functions which cause a thread to yield without having to do anything extra. So when I call a function from C in a LUA script I do something like this:

g_currentLuaState = lua_newthread(s->luaState);
lua_pushstring(g_currentLuaState,"functionName");
lua_gettable(g_currentLuaState, LUA_GLOBALSINDEX);

//push any arguments on to the stack

lua_resume(g_currentLuaState, numberOfArguments);
This seems to work fine up to a point where it crashes. My game calls an update function in the test script I'm using every frame. The first 60 or so times it does this it works fine, however it eventually crashes. My first though was it was some kind of memory leak due to me creating so many threads. However the LUA documentation says that they are cleaned up automatically by the LUA garbage collector and in any case calling lua_close on it causes a crash, presumably because it clears up the global environment which it shares with the scripts main state (the I create all the threads from). I'm not sure if this crash is because of something subtle error in my coding somewhere, or something to do with LUA that I'm not realising. Has anyone ever encountered a similar crash? Does anyone know what might be causing it and how I could deal with it?
Advertisement
I think that you should probably use a single lua_state.

I'm not 100% sure about this, but I think lua_newthread should only be called if you're creating a new native C thread, and you should then have one lua_state per thread.

You shouldn't loop around creating new ones.

I don't think that lua_newthread is the same as creating a coroutine, it's something completely different.

Mark
Hmm prehaps you are right, the docs don't seem overly clear here:

Quote: Lua offers partial support for multiple threads of execution. If you have a C library that offers multi-threading, then Lua can cooperate with it to implement the equivalent facility in Lua. Also, Lua implements its own coroutine system on top of threads. The following function creates a new thread in Lua:

lua_State *lua_newthread (lua_State *L);



It does seem like it will create a new thread rather than just a coroutine. Though I don't see why creating new threads constantly is gonna crash the program (slow it down maybe, but LUA should be cleaning them up so there should be no problems with memory leaks or whatever).

Anyway my goal is to be able to call a c function that returns lua_yield (e.g. pauses script execution so the game engine can go do something else while waiting for an event to occur, such as an NPC reaching the edge of the screen, before continuing script execution) from any point in a Lua script without having to do anything special. Though I guess if it takes up far more resources to create a new thread every time and run functions in the new thread and hence causes crashes (and it looks like it does) I could mark the functions that call the c functions which call lua_yield as ones to run in seperate threads, while the rest are run normally using lua_pcall( ).
You absolutely, definitely, cannot yield in the middle of a C function called from lua. A coroutine does not contain a snapshot of the C stack at that point.

What you can do, is yield from a lua-based wrapper for that function, this works nicely. You could make a C function return some status to the lua to tell it that it should yield before continuing, or have a wrapper which loops around, alternately calling a function and yielding until it gets the right result.

Then at a later point you can resume the thread by calling a lua wrapper to resume. That works for me anyway.

In any case, you don't need a separate lua_state for each object, the only thing you need to store is the coroutine object itself. I use luabind and a luabind::object to store the coroutine, that seems to work.

Anyway I managed to make it so that a NPC object can be scripted using a lua coroutine. And I only need one lua_state

Mark
Quote: You absolutely, definitely, cannot yield in the middle of a C function called from lua


You can't yield in the middle of a c function but you can yield at the end by doing return lua_yield( );

Quote: In any case, you don't need a separate lua_state for each object, the only thing you need to store is the coroutine object itself.


What do you mean by each object? Each different script you may load? I have a seperate lua_state for each one because they need to have different global environments. And as far I know a coroutine is a lua_state (at least when you pop a thread object off the stack in the lua c API it gives you a lua_state* ).

Quote: What you can do, is yield from a lua-based wrapper for that function, this works nicely. You could make a C function return some status to the lua to tell it that it should yield before continuing, or have a wrapper which loops around, alternately calling a function and yielding until it gets the right result.


This may be what I have to do, but I was trying to avoid having to explicitly create a coroutine in LUA, ahh well I guess it doesn't really matter.

This topic is closed to new replies.

Advertisement