罕見的coredump了


最近,項目在越南版刪檔測試的時候,發生了罕見的coredump,簡單記一點排查日志

 

目前的敏感詞過濾是在C層做判定的,先后經過幾個項目考驗,模塊算是比較穩定了。越南版有個需求,需要將敏感詞里的空格去掉。比如敏感詞是abc,現在不能說abc了,但是玩家可以輸入“a b c”,所以需要過濾掉空格。有同事就對C層改了一下,判斷rune是32的時候,就繼續判斷后續字符,出事的代碼大致如下:

        lua_rawgeti(L, 1, j);             
        uint32_t rune = (uint32_t)lua_tointeger(L, -1); + if (rune == 32) { + continue; + } lua_pop(L, 1); - if(node == NULL) { node = table_get(dict, rune); } else {

這里會跳過lua_pop語句,導致之前lua_rawgeti的結果殘留在棧上。但這個缺陷不會馬上讓進程掛掉,而是將棧弄壞一點點。我們來看Lua的棧定義:

 1 /*
 2 ** 'per thread' state
 3 */
 4 struct lua_State {
 5   CommonHeader;
 6   unsigned short nci;  /* number of items in 'ci' list */
 7   lu_byte status;
 8   StkId top;  /* first free slot in the stack */
 9   global_State *l_G;
10   CallInfo *ci;  /* call info for current function */
11   const Instruction *oldpc;  /* last pc traced */
12   StkId stack_last;  /* last free slot in the stack */
13   StkId stack;  /* stack base */
14   UpVal *openupval;  /* list of open upvalues in this stack */
15   GCObject *gclist;
16   struct lua_State *twups;  /* list of threads with open upvalues */
17   struct lua_longjmp *errorJmp;  /* current error recover point */
18   CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
19   volatile lua_Hook hook;
20   ptrdiff_t errfunc;  /* current error handling function (stack index) */
21   int stacksize;
22   int basehookcount;
23   int hookcount;
24   unsigned short nny;  /* number of non-yieldable calls in stack */
25   unsigned short nCcalls;  /* number of nested C calls */
26   l_signalT hookmask;
27   lu_byte allowhook;
28 };

lua_State的stack是一個指針,指向一個動態申請的TValue指針數組。這個棧不僅是lua和C交互的時候,用於雙方交換數據;lua函數調用的時候,也會將函數參數壓棧(當然,調用關系不在這個棧上,而是通過CallInfo指針組織的雙向鏈表來記錄)Lua默認會給函數初始化20個格子,也可以通過lua_checkstack函數去增加棧的大小。L->top指向的是棧上的第一個可用空槽,L->top在正常使用的時候會小於L->ci->top,lua自帶有api_check來檢查。之前為了壓榨性能,api_check也關掉了,所以沒檢查出stack overflow。

 

當一個C函數不斷往棧上push函數,超過棧的大小后,會寫壞什么內存就沒法確定了。出事的時候,寫壞的是另一個協程的stack,另一個協程正准備resume回來,但是棧上存的ci->func是TValue(正數32),不是一個函數類型,就coredump了。

 

穩妥起見,以后改C代碼還是走一下code review吧,自己也打開api_check檢查一下。。查這個問題花了很久,還有一個原因是其他同學搞混了線上版本,我看的是有問題的版本,結果另一個分支上的是沒問題的版本,以為正式服上跑的是沒問題的版本,查了好久。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM