skynet版本:v1.4.0 (2020-11-16)
最近在做武侠mmo的游戏。因为武侠战场有一个tick在计算状态,然而在tick里的逻辑出现了问题,具体原因是一个怪物的ai返回错误码值有问题,而外层tick又没有捕捉到这个错误码,所以出现了死循环,导致一直在执行ai,创建了一堆table,最后导致内存爆了。
这里不讨论逻辑问题,主要讲述当时是如何定位到bug代码的,然后可以如何改进。
当时得亏还在内测阶段出现问题,而且这个是可以重现的,具体表现是在固定的副本里的固定的怪物释放了固定的技能导致,当然这是找到的结果。
在出现问题的时候,因为是比较难触发到,所以也无法立刻判断出是技能的bug,在重现过程中,依赖于skynet本身的debug_conole 的 signal 1命令来输出当前的堆栈,最终也能定位到问题。
解决完bug后,后面想如何能在出现问题的时候尽可能得收集到当前bug的相关信息呢?回想到查找bug的过程,主要还是要打印当前的堆栈,所以想是否能在 monitor 线程监控的时候发现死循环时打印出lua当前的堆栈呢?觉得是可行的,因为signal 1 的信号实际也是调用了c层面的方法而已。
很容易的,能够想到在 skynet_monitor.c 里加入如下代码,直接调用command接口:
void
skynet_monitor_check(struct skynet_monitor *sm) {
if (sm->version == sm->check_version) {
if (sm->destination) {