猿问

我的修改方案就是直接将 fflush(NULL)这句去掉,这样做会不会有什么风险?

c程序中使用lua5.3.2库来实现程序与lua脚本的调用,设计概要:
1. 多线程调用lua的接口来实现对lua脚本的调用
2. 多线程调用system实现其他任务
这样做概率性的会出现程序死锁问题,下面是部分的堆栈信息:
Thread 8 (Thread 0x7f7ae46f0700 (LWP 14392)):
#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007f7b7aa7653d in _L_lock_121 () from /lib64/libc.so.6
#2 0x00007f7b7aa74103 in __GI__IO_un_link () from /lib64/libc.so.6
#3 0x00007f7b7aa6611d in fclose@@GLIBC_2.2.5 () from /lib64/libc.so.6
#4 0x000000000046b2db in io_fclose ()
#5 0x000000000045c1dc in luaD_precall ()
#6 0x00000000004665a5 in luaV_execute ()
#7 0x000000000045c59c in luaD_call ()

Thread 4 (Thread 0x7f7ae26ec700 (LWP 14396)):
#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007f7b7aa76640 in _L_lock_4452 () from /lib64/libc.so.6
#2 0x00007f7b7aa75a08 in _IO_flush_all_lockp () from /lib64/libc.so.6
#3 0x000000000046ba63 in io_popen ()

Thread 181 (Thread 0x7f7b3af9d700 (LWP 14197)):
#0 0x00007f7b7ab03d1c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007f7b7aa76728 in _L_lock_6097 () from /lib64/libc.so.6
#2 0x00007f7b7aa7647f in __GI__IO_list_lock () from /lib64/libc.so.6
#3 0x00007f7b7aabd087 in fork () from /lib64/libc.so.6
#4 0x000000000044a302 in systemEx 
经过定位,io_popen调用了l_popen
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
问题就在这句 fflush(NULL),这是这个操作导致了死锁

翻过高山走不出你
浏览 172回答 1
1回答

长风秋雁

在C中调用Lua函数的API主要由以下几个:(1)void lua_call (lua_State *L, int nargs, int nresults);函数调用,nargs表示参数的个数,nresults表示返回值的个数首先将lua函数压栈,然后将参数依次压栈,最后调用函数即可函数调用时,参数和函数都会pop出栈,调用返回后,结果会push进栈nresults==LUA_MULTRET,所有的返回值都会push进栈nresults!=LUA_MULTRET,返回值个数根据nresults来调整Lua语句:a = f("how", t.x, 14)在C中的实现:lua_getglobal(L, "f");        // 函数入栈lua_pushstring(L, "how");     // 参数1入栈lua_getglobal(L, "t");       // 表t入栈lua_getfield(L, -1, "x");      // 参数2入栈lua_remove(L, -2);        // 跳t出栈lua_pushinteger(L, 14);     // 参数3入栈lua_call(L, 3, 1);        // 调用函数,参数和函数都会出栈lua_setglobal(L, "a");     // 给a赋值,栈顶出栈上述代码执行完毕后,堆栈状态恢复原样。(2)int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);函数调用,在安全模式下,并且可以添加错误处理函数。如果调用期间发生error,lua_pcall会捕获之,然后push stack一个错误信息(会先将函数和参数pop出栈),并且返回一个error code(非0的一个值)。发生error时,如果指定了错误处理函数,会在error message入栈前调用错误处理函数,具体由msgh参数来决定:(1)msgh==0,不指定错误处理函数,入栈信息不变;(2)msgh!=0,msgh表示错误处理函数的堆栈index,错误处理函数会以error message为参数,并将返回的新的errormessage入栈。主要用来给error message添加  更多的debug信息,比如堆栈跟踪,因为这些信息在pcall调用完之后是收集不到的。函数返回代码:LUA_OK(0):调用成功LUA_ERRRUN:runtime errorLUA_ERRMEM:内存分配错误,这种情况下不会调用错误处理函数LUA_ERRERR:调用错误处理函数时出错,当然,不会再进一步调用错误处理函数LUA_ERRGCMM:调用metamethod.__gc时报错,由gc引起,和函数本身没关系(3)int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k);函数调用,在安全模式下,并且允许函数yield
随时随地看视频慕课网APP
我要回答