ycsm宕机、bug记录
1、__stack_chk_fail宕机
- 今天云海服务器发生了宕机,堆栈如下:
#0 0xf77a4440 in __kernel_vsyscall ()
#1 0xf74af687 in raise () from /lib/i386-linux-gnu/libc.so.6
#2 0xf74b2ab3 in abort () from /lib/i386-linux-gnu/libc.so.6
#3 0xf74e9fd3 in ?? () from /lib/i386-linux-gnu/libc.so.6
#4 0xf757f03b in __fortify_fail () from /lib/i386-linux-gnu/libc.so.6
#5 0xf757efca in __stack_chk_fail () from /lib/i386-linux-gnu/libc.so.6
#6 0x08212e51 in CGMActivitySys::OnRelevancePhone (this=0xe22f9e0, player=…, phoneNum=0x12c85ab4 “19907316909”, cdKey=0x1525e54c “446244”)
at game_sys/gm_activity/gs_gm_activity.cpp:4572
#7 0x0821275f in CGMActivitySys::OnC2S_RelevancePhone (this=0xe22f9e0, player=…, request=0xfff0bee8, errMsg=…)
at game_sys/gm_activity/gs_gm_activity.cpp:4477
#8 0x08356672 in MgrGameWorld::OnReceiveProtoEvent (this=0xce2e5f4, player=0x14fd9f10, eventID=CtmGame::C2SG_RELEVANCE_PHONE, request=0xfff0bee8,
response=0xfff0bf14) at game_sys/base/game_world.cpp:222
#9 0x085aa79f in PlayingGameProcessor::OnReceiveMsg (this=0x11954030, pClient=0x14eede78, eventID=2434, request=0xfff0bee8, response=0xfff0bf14)
at login_sys/impl/login_processor/PlayingGameProcessor.cpp:198
#10 0x0854aed2 in NetManagerListenForGate::OnReceiveMSG (this=0xb605638, pSession=0x14eede78, gameSysID=0 ‘\000’, packet=0x1195902c)
at net_sys/gate/gate_server.cpp:532
查了一下__stack_chk_fail ()的说明,访问链接:__stack_chk_fail ()
查看链接后,证实代码确实有数组越界了,分析上下文,最终发现是一处拼接url的地方,写数组越界。
源码:
char url[128];
sprintf(url,gsCfg->PhoneURL,gsCfg->gameName,oid_s,phoneNum,act_s);
这里拼接的字符串超出128字节了,原因是随着项目的运行,增开的服务器越来越多,终于有一天,开到了sstx100,原先sstx99不会越界,但是gameName为sstx100时,拼接后长度正好129,越界。
2、宕机
-
记一次外网验收服务器的core文件分析,堆栈信息如下:
Program terminated with signal SIGABRT, Aborted.
#0 0xf76e7440 in __kernel_vsyscall ()
(gdb) bt
#0 0xf76e7440 in __kernel_vsyscall ()
#1 0xf73f2687 in raise () from /lib/i386-linux-gnu/libc.so.6
#2 0xf73f5ab3 in abort () from /lib/i386-linux-gnu/libc.so.6
#3 0xf742cfd3 in ?? () from /lib/i386-linux-gnu/libc.so.6
#4 0xf74374ca in ?? () from /lib/i386-linux-gnu/libc.so.6
#5 0xf74382d9 in ?? () from /lib/i386-linux-gnu/libc.so.6
#6 0x085f8d17 in operator delete (pointer=0xd9be110) at main.cpp:48
#7 0x080aa545 in CFriendSystem::OnPlayerDestroy (this=0xee47370, player=0xd2b6ce0) at game_sys/friend/gs_friend.cpp:1043
#8 0x088ff60a in EvEventBroadcastImp::ProcessEventArgPtr (this=0xbeef088, ev=0x97cc220 <_ZL17EV_PLAYER_DESTROY>, data=0xffafeb20) at ev_event_broadcast_imp.cpp:239
#9 0x088ff7a8 in EvEventBroadcastImp::ProcessEventArgs (this=0xbeef088, ev=0x97cc220 <_ZL17EV_PLAYER_DESTROY>, iNumArgs=1) at ev_event_broadcast_imp.cpp:470
#10 0x0892d107 in EvEventBroadcast::SendEvent (this=0xbeef088, ev=0x97cc220 <_ZL17EV_PLAYER_DESTROY>, a1=…) at ev_event.cpp:153
#11 0x085b8d2b in CPlayer::OnBeforeOffline (this=0xd2b6ce0) at player_sys/impl/player_sys.cpp:775
#12 0x085be0fe in CPlayerMgr::RemoveOnlinePlayer (this=0xc3188a8, aaa@qq.com: 2314902248876802048) at player_sys/impl/player_sys.cpp:1842
#13 0x085c0d30 in CMessageExtenedHandler::on_handle_msg<(unsigned short)207> (pClient=0xd465b80, pPacket=0xc07e2a4) at player_sys/impl/player_sys.cpp:2485
#14 0x085a7e78 in NetManagerListenForGame::_Handle (this=0xa5f5298, conn=0xccb9fa0, ProtoID=207, packet=0xc07e2a4) at net_sys/game/game_server.h:17
#15 0x080a413d in CCLNetSocketServer::_baseOnConnectionReceive (this=0xa5f5298, sess=0xccb9fa0, ProtoID=207, packet=0xc07e2a4)
at …/common_engine/common/net/api/cl_net_socket_server.h:128
#16 0x088798eb in CCLNetSocketServerBase::__lambda0::operator() (__closure=0xc926d70, conn=0xd465b80, packet=0xc07e2a4) at common/net/cl_net_socket_server.cpp:182
#17 0x08879fc7 in std::_Function_handler<void(EV_NetClient*, EvMemPacket*), CCLNetSocketServerBase::OnReceive(EV_NetServer*, EV_NetClient*, EvMemPacket*)::__lambda0>::_M_invoke(const std::_Any_data &, EV_NetClient , EvMemPacket ) (__functor=…, __args#0=0xd465b80, __args#1=0xc07e2a4) at /usr/include/c++/4.8/functional:2071
#18 0x0887e9e8 in std::function<void (EV_NetClient, EvMemPacket)>::operator()(EV_NetClient*, EvMemPacket*) const (this=0xffafef1c, __args#0=0xd465b80, __args#1=0xc07e2a4)
at /usr/include/c++/4.8/functional:2471
#19 0x0887e988 in cl_net_proxy::rcv(EV_NetClient*, EvMemPacket&, std::function<void (EV_NetClient*, EvMemPacket*)>) (this=0xdf19850, pClient=0xd465b80, pkt=…, rcv_cb=…)
at common/net/net_packet/cl_net_proxy.cpp:73
#20 0x08879a2b in CCLNetSocketServerBase::OnReceive (this=0xa5f5298, server=0xc07e248, conn=0xd465b80, packet=0xc07e2a4) at common/net/cl_net_socket_server.cpp:187 -
1、堆栈第#6行,提示的是delete指针的时候,导致发生了coredown;这里是项目重载了delete操作符,用来做内存统计的。
-
2、看到报错信息是:Program terminated with signal SIGABRT, Aborted.,猜测是delete了一个非法指针。一开始怀疑是double kill,delete了两次。但是进入#7行,分析指针的数据看上去并没有野掉,所以应该是第一次delete。
-
3、所以再怀疑是内存被踩越界了,导致了非法指针。项目有几十万行代码,最讨厌的就是找内存越界,要老命啊!所幸运气好,这里再往上追踪,是玩家离线的时候,抛出事件EV_PLAYER_DESTROY来销毁每个系统挂载的玩家数据。那么一般情况下,可以认为是上一个游戏系统非法操作,破坏了内存,导致下一个系统再使用内存的时候,挂逼了。然后再去分析游戏log文件,找到上一个系统gs_yunshi,该系统新开发的玩法,并且和QA确认了下,宕机时间点,外网验收正好有人在测试该玩法。嗯,好像找到一个重点嫌疑犯了。
-
4、然后就是去review该系统的代码,果然发现有这么一段代码:
auto iter = _info_map.find(act_id);
iter->second.act_id = act_id;
iter->second.act_time = nowtime;
这里iter如果等于_info_map.end()的话,那么2、3行的写数据行为,就极有可能破坏内存,把后面的内存写坏了。这段代码是在活动开启的时候触发的,接下来就是模拟操作,然后复现一下coredown文件;按操作成功复现了core文件。然后再修改这段代码,再同样模拟操作,没宕。好了,可以收拾东西回家睡觉了。
这里记一下查内存越界的思路:
- 1、一般都是因为上文非法操作了内存,导致下文的内存可能被写坏了,所以可以先把上文列为重点嫌疑对象。
- 2、分析下core文件和日志信息,定位到关键操作(玩家下线了、玩家参与了某个活动等等)或关键函数。
- 3、有嫌疑对象、关键信息以后,还没有查到结果,那就review代码,分析的时候不要心急,因为它宕了就一定会留下痕迹,所以总能找到蛛丝马迹。
- 4、定位问题以后,就模拟操作,重现宕机。
- 5、改正代码,再模拟操作,确认不会发生宕机。
3、记一次恶心BUG的查询
- 1、策划把炼狱挑战转移到封魔录中,所以需要在玩家登陆的时候,做一次老数据的转换。将外网玩家的炼狱挑战的进度映射到封魔录中。
- 2、假设封魔录进度有6关,如果封魔录没有通过 6关,那么在在主界面会显示封魔录的按钮,如果6关都通关了,那么主界面隐藏封魔录按钮。
- 3、由于玩家已经完成炼狱挑战的6关,那么转换到封魔录,对应的进度,也应该是6关都通过了,那么主界面应该隐藏封魔录。
出现bug情况是:有个玩家通关了炼狱6关,但是在主界面出现了封魔录的按钮。当时不知道原因是什么,怕玩家可以再打一次炼狱挑战,拿6个关卡的奖励,于是通宵查了一晚上,分析了所有代码,最终还是一无所获。困惑了一晚上,后来灵光一闪,用延迟工具设置了网络延迟,终于复现了bug。
- 最终的原因是:服务器的数据发包晚了,客户端在没有完全收到服务器数据的时候,就去初始化主钮界面的封魔录按钮;并且服务器的数据包在随后下发到客户端时,由于客户端界面已经初始化完成,未根据服务器数据再刷新一下界面,丢弃了本次服务器的数据,最终导致BUG。
上一篇: STM32复习笔记 1-矩阵键盘
下一篇: 数据库之——sqlite下载及使用
推荐阅读
-
Django开发学习BUG记录--RemovedInDjango19Warning:Model class apps.user.models.User doesn't declare an explicit app_label
-
记录Window系统下myeclipes连接linux下mysql所出现的一个bug
-
记录一次BUG修复-Entity Framwork SaveChanges()失效
-
Bug: 删除中间某条记录后/删除最后一条记录再添加 ,auto-increment的自动增长不连续
-
【openmv】openmv各种bug问题记录
-
微信小程序bug记录与解决
-
pytorch遇到的bug记录—2
-
关于微信小程序bug记录与解决方法
-
java爬虫爬取的bug记录
-
记录vue用 html5+做移动APP 用barcode做扫一扫功能时安卓 的bug(黑屏、错位等等)和解决方法