4

Context: I am working on a set of bindings, and many of my functions reference the "global" Lua state. (It's not actually global in the code I am developing, but local to the particular runtime instance, so global in that all of the callback functions have access to shared state.)

The Lua documentation does not seem to specify whether the pointer passed to a lua_CFunction is guaranteed to be a pointer to the exact same lua_State object as was used to invoke the function (directly via lua_cpcall() or indirectly by invoking Lua code that invokes the C function).

A small test shows that the pointers reference the same object, but I do not know if this is guaranteed.

#include <stdio.h>
#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>

static lua_State *state;

static int test_fn(lua_State *L)
{
    printf("global:%p local:%p\n", state, L);
    return 0;
}

int main(int argc, char const **argv)
{
    state = luaL_newstate();

    luaL_openlibs(state);
    lua_register(state, "test_fn", test_fn);

    luaL_dostring(state, "test_fn()");

    lua_close(state);
}

Example output:

global:0x87ef008 local:0x87ef008

I know that Lua gives the function a stack that contains only the arguments to that function, and that makes me a bit uneasy that perhaps this could be implemented by passing that function a different state pointer that is tracking an independent stack. It could also be implemented any number of other ways that would not require a different lua_State -- and in fact I expect that it does work this way -- but the documentation doesn't seem to explicitly say either way.

Are these pointers guaranteed to be equal? If not, under what circumstances might they differ?

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • The state passed in luaL_dostring will always be the same as the state received by test_fn if test_fn is called in luaL_dostring (or dofile). It is possible to have more than one state open though so I would not say guaranteed. – Nick Van Brunt Jul 11 '13 at 18:34
  • @Nick Right -- that's why I specify "the same state as used to invoke the function." :) Of course different states will be passed to the function when it is invoked from different states. – cdhowie Jul 11 '13 at 18:36

2 Answers2

6

If your C function is called from Lua code, then the lua_State argument will be the Lua thread of the calling Lua function.

If your Lua code does not use coroutines, there is only one thread, so you will always get the global state.

Doug Currie
  • 40,708
  • 1
  • 95
  • 119
  • Does this mean that if I want such a guarantee, I must not allow Lua code to create coroutines? (The code that will run is untrusted.) – cdhowie Jul 11 '13 at 18:40
  • Yes; you can (a) remove the coroutine functions from your sandbox, or you can (b) deal with having different states supplied to your C functions... why is this a problem? In Lua 5.2 you can get the global Lua state from any C function using `LUA_RIDX_MAINTHREAD`. – Doug Currie Jul 11 '13 at 19:01
  • It's not a problem, just something I am trying to account for in my API design. I'm using Lua 5.1, but I can still get the main thread pointer from another thread by storing it in the registry as light userdata when initializing my runtime object. – cdhowie Jul 11 '13 at 19:37
0

Doug's answer is correct, but to further elaborate, the state pointer is -not- guaranteed to be the same, and will most likely be different, when you use coroutines.

For an example of this going wrong, see the problem I was just in a few hours ago.

Panda Pajama
  • 1,283
  • 2
  • 13
  • 31