lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Friday 15, jseb wrote:
> Hello,
> 
> I've got a thread started inside a library. This thread calls a Lua
> function from the Lua script which required this library.
> Between each loop, the thread is waiting one second

The standard Lua interpreter is not re-entrance safe.  You will have to build 
a custom interpreter which uses locks to only allow one thread to access the 
lua_State object at a time.

I wouldn't recommend doing this anyways since it will not scale.  It would be 
better to use one lua_State per thread and use message passing for 
communication between the threads.

> I've encounters random hangs while running it:
> 
> - segfault as soon as the Lua script is launched.
> - one second wait, then segfault.
> - never return, nor show anything (manual termination with ctrl+c)
> - sometimes, some cryptic curses from Lua interpreter, like:
> 
> lua: attempt to concatenate a nil valueattempt to call a nil value
> stack traceback:
>          [C]: in function 'clock'
>          ./test_libfoo.lua:14: in main chunk
>          [C]: ?
> 
> (line 14 is: while os.clock() - timer <= 5 do end )
> 
> The funny thing is it seems that it is my temporisation which disturb Lua:
> timer = os.clock()
> while os.clock() - timer <= 5 do end
> 
> 
> Worse, an "old school temporisation" works;
> for i=0,300000000 do end
> 
> 
> I know the problem is not my temporisation, as the first version (with
> "os.clock()" ) is working in a standalone script.
> 
> I think i have a serious problem here, and i'm not waiting for you for
> debugging my experiments. Which annoys me is that i was trying to write
> a short program for isolating another problem i encounter with
> re-entrance in Lua :(
> So, i'm opened to all suggestions for solving the drifting problem.
> 
> Thank you.
> 
> 
> Here is the complete Lua script:
> 
> #!/usr/bin/env lua
> 
> foo = require ("libfoo")
> 
> function lua_callback()
>     print ("I am the function located in Lua script")
> end
> 
> foo:set_callback (lua_callback)
> 
> 
> -- this one hangs
> timer = os.clock()
> while os.clock() - timer <= 5 do end
> 
> -- this old school temporisation works :
> --for i=0,300000000 do end
> 
> foo:end_callback ()
> 
> 
> 
> And here is my C library:
> /* for testing re-entrance with Lua
>    gcc -o libfoo.{so,c} -fvisibility=hidden -pthread -shared -fPIC -Wall
> */
> 
> #include <stdio.h>
> #include <unistd.h>
> #include <pthread.h>
> #include <lua.h>
> #include <lauxlib.h>
> 
> pthread_t my_thread;
> int thread_is_running = 0;
> 
> static void fx_callback (lua_State *L)
> {
>      static lua_State *L_context = 0;
>      static int index_fx_lua = LUA_REFNIL;
> 
>      if (L) { // initialised only at startup
>      L_context = L; // we store the context
>      // and store the function given as Lua parameter
>      index_fx_lua = luaL_ref (L, LUA_REGISTRYINDEX);
>      if (index_fx_lua == LUA_REFNIL) {
>        fprintf(stderr,"luaL_ref : erreur\n");
>      }
> 
>    } else { // it was called from the thread loop
>      lua_rawgeti (L_context, LUA_REGISTRYINDEX, index_fx_lua);
>      lua_pcall(L_context, 0,0,0);
>    }
> }
> 
> static void * fx_thread(void *arg)
> {
>    while (thread_is_running) {
>      fx_callback(0);
>      sleep(1);
>    }
>    return 0;
> }
> 
> 
> static int set_callback(lua_State *L)
> {
>    fx_callback (L);
>    thread_is_running = 1;
>    pthread_create ( &my_thread, NULL, fx_thread, NULL);
>    return 0;
> }
> 
> static int end_callback(lua_State *L)
> {
>    void *ret = 0;
>    fprintf (stderr,"waiting for thread to finish\n");
>    thread_is_running = 0;
>    pthread_join (my_thread, &ret);
>    return 0;
> }
> 
> static const struct luaL_Reg foo_fx [] = {
>      { "set_callback", set_callback },
>      { "end_callback", end_callback },
>      {NULL,NULL}
> };
> 
> 
> #ifdef __linux
> __attribute__((visibility("default"))) int luaopen_libfoo(lua_State *L)
> #else
> __declspec(dllexport) int luaopen_libfoo(lua_State *L)
> #endif
> {
>    luaL_register (L, "foo", foo_fx);
>    return 1;
> }


-- 
Robert G. Jakabosky