码迷,mamicode.com
首页 > 其他好文 > 详细

libuv 定时器错误使用引发的惨案

时间:2018-03-29 10:26:52      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:create   str   代码   audio   指针   efault   manage   测试过程   tor   

今天我们正在开发的游戏在测试过程中,服务器又挂了,用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指针,让它的变成了一个未分配的内存地址,然后在新定时器加入进行插入队列的操作时候触发了段错误。
 
 

libuv 定时器错误使用引发的惨案

标签:create   str   代码   audio   指针   efault   manage   测试过程   tor   

原文地址:https://www.cnblogs.com/doublerain/p/8667724.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!