Skip to main content
gamedev.net
🔒 Locked

strange lua memory error with new thread!

Started by ericgu Feb 20, 2009 at 9:36 PM 4 replies 1.6k views
Original Post
ericgu
ericgu
I use lua in game server .I want to listen an event in lua ,so I need create a new thread with the same lua evironment.But a strange error happeds :memory error.Check the following code: lua_bug.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#include <pthread.h>

/* args passed by thread
*/
typedef struct wrap_recv{
	lua_State *Lr;
	char func_name[124];
}WRAP_RECV;

static int recv_wrap(WRAP_RECV*wr){
	pthread_detach(pthread_self());
	lua_State *Lr = wr->Lr; //the child lua_State
	char *fun = wr->func_name;  	//get the callback function name 
	int i = 0;
	while(1){
		lua_getglobal(Lr,fun);
		lua_pushnumber(Lr,i);
		lua_call(Lr, 1, 0);
		i++;
	}
}

static int lua_listen(lua_State *L) {
	lua_State * Lr = NULL;
	char *fun = (char*)lua_tostring(L, 1);	
	Lr = lua_newthread(L);	//get a new lua_State
	if (Lr == NULL)
		luaL_error(L, "cannot create new stack");
	/* create a hard reference to the thread object into the registry */
	lua_pushlightuserdata(L, Lr);
  lua_insert(L, -2);
  lua_settable(L, LUA_REGISTRYINDEX);
	
	WRAP_RECV*wr = (WRAP_RECV*)malloc(sizeof(WRAP_RECV));
	wr->Lr = Lr;
	strcpy(wr->func_name,fun);
	
	pthread_t thread_id;	
	/* create a new thread of execution and we are done */
	int	res = pthread_create(&(thread_id), NULL, (void *) recv_wrap,
				wr);	
	lua_pushinteger(L, res);	
	return 1;
}

static int lua_printtest(lua_State *L) {
	int i = (int)lua_tointeger(L, 1);	
	printf("thread parent : %d\n",i);
	return 0;
}


static luaL_Reg bugoperatelib[] = {
	{	"listen", lua_listen },
	{	"printtest", lua_printtest },
	{ NULL, NULL } };

int init(lua_State*L) {
	luaL_register(L, "bug", bugoperatelib);
	return 1;
}



lua script

function fun_callback(pt)
print("thread child : "..pt)
end

package.loadlib("libbug.so", "init")();

bug.listen("fun_callback")

i = 1;
while i<5000000 do
	str = string.format("name%d",i);
	bug.printtest(i);
	i = i+1;
end

while 1 do
end


You need compile the c file , gcc -fPIC -shared -olibbug.so lua_c.c -llua -ldl -lm -lpthread cp libbug.so /usr/lib then use the modul in lua script.Running lua file ,it will be Segmentation fault,or memory double free. The error will not appear every time ,or in a short time ,so you need test it more if the error does not show up. Also I test it without the lines " str = string.format("name%d",i);",the error shows up less. So can anyone tell me what happens ? Thank you
ddn3
ddn3
You can't access the same Lua vm on multiple threads simultaneously. Lua isn't thread safe in that sense. You'll have to do the standard paradigm in thread programming and create a message pump or something from the thread which u run the Lua vm, and feed it events there.

Or you can extend Lua to be native thread aware and do ur threading inside Lua itself, with one of the Lua extension libraries ie.

http://www.tecgraf.puc-rio.br/~diego/professional/luathread/

this way Lua does the threading and is self consistent, if that's acceptable.

Good Luck!

[edit : u can also place mutex around the pcall to the VM, that might prevent simultaneous access]

-ddn
ericgu
ericgu
Thanks for your suggestion!
But I'm still confused where I should put the mutex in lua script.What should I lock?
If I lock the pcall like this:
static int recv_wrap(WRAP_RECV*wr){	pthread_detach(pthread_self());	lua_State *Lr = wr->Lr; //the child lua_State	char *fun = wr->func_name;  	//get the callback function name 	int i = 0;	while(1){		pthread_mutex_lock(&s_mutex);// set a mutex		lua_getglobal(Lr,fun);		lua_pushnumber(Lr,i);		lua_call(Lr, 1, 0);		pthread_mutex_unlock(&s_mutex);		i++;	}}

What should i do in the script?
ddn3
ddn3
That's fine, since Lua isn't thread safe, you can't access any Lua functions across threads without some sort of guard like so. Inside Lua your code will just run as if it was executing sequentially and so it's internally state will be stable.

Each Lua thread has its own stack, which will allow you to keep statefull execution between pcalls, if that's what your wondering, but that's really only needed if your modeling your logic on parallel execution threads, which has its own pros and cons.

Good Luck!

-ddn
ericgu
ericgu
I call c from lua ,when the c function creates a thread then run " pcall ".At the same time inside lua script is still runing,so i think there is no way to use mutex.
are i right or i didn't understand it
ddn3
ddn3
Your correct, I didn't read the code well enough, it looks like your spawning the new thread inside the execution context of the current Lua vm, then spinning in a loop waiting for the 2nd thread to process data.

I suggest looking at the Lua thread exentsions, which allow seamless native threading inside Lua itself, which solves most of the problem of multiple threads accessing a running Lua vm for you.

Good Luck!

-ddn

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.