libuv 定時器錯誤使用引發的慘案


今天我們正在開發的游戲在測試過程中,服務器又掛了,用gdb加載core文件后看到最后的堆棧信息如下

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fa57d86da66 in uv_timer_init (loop=0x7fa57da7bc80 <default_loop_struct>, handle=0x2081e28) at src/unix/timer.c:55
#1  0x000000000043d326 in Room::Room(int, bool) ()
#2  0x00000000004437e7 in RoomManager::creatRoom(std::vector<Player, std::allocator<Player> >&) ()
#3  0x0000000000491506 in AsyncCreateRoomTask::run() ()
#4  0x000000000040accf in timer_cb(uv_timer_s*) ()
#5  0x00007fa57d86df1e in uv__run_timers (loop=loop@entry=0x7fa57da7bc80 <default_loop_struct>) at src/unix/timer.c:165
#6  0x00007fa57d861f72 in uv_run (loop=0x7fa57da7bc80 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:350
#7  0x0000000000409ca9 in main ()

查看libuv的源碼,是下面代碼引起的錯誤

uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER);

對應的宏定義是

#define uv__handle_init(loop_, h, type_)                                      \
  do {                                                                        \
    (h)->loop = (loop_);                                                      \
    (h)->type = (type_);                                                      \
    (h)->flags = UV__HANDLE_REF;  /* Ref the loop when active. */             \
    QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue);            \
    uv__handle_platform_init(h);                                              \
  }                                                                           \
  while (0)

檢查了loop和uv_timer_t均為有效指針,並且排除有多線程的競爭操作。

查看uv_timer_t的loop和type以及flags都正常賦值,於是基本鎖定錯誤源在QUEUE_INSERT_TAIL 這個插入隊列尾部的操作。
在尾部插入操作中,需要將loop的pre指向節點的next設置為uv_timer_t,但是讀取loop的pre指向的是一個未分配內存的地址,然后觸發了段錯誤。
 
下午幾個小時經過細致的代碼檢查,終於找到了錯誤原因:libuv一個timer的結束需要調用uv_close,而原來一直只調用了uv_timer_stop,並且把uv_timer_t給delete掉了。由於沒有調用uv_close,uv_timer_t還在loop的handle_queue中,在很小的機會下,系統之后又將原來這個uv_timer_t的空間分配給了其他對象,而這個對象剛好又修改到了原來handle_queue的next指針,讓它的變成了一個未分配的內存地址,然后在新定時器加入進行插入隊列的操作時候觸發了段錯誤。
 
 


免責聲明!

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



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