CN103810053B - 网络游戏服务器陷入死循环的处理方法 - Google Patents
网络游戏服务器陷入死循环的处理方法 Download PDFInfo
- Publication number
- CN103810053B CN103810053B CN201410050333.5A CN201410050333A CN103810053B CN 103810053 B CN103810053 B CN 103810053B CN 201410050333 A CN201410050333 A CN 201410050333A CN 103810053 B CN103810053 B CN 103810053B
- Authority
- CN
- China
- Prior art keywords
- lua
- endless loop
- message
- absorbed
- thread
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Landscapes
- Computer And Data Communications (AREA)
Abstract
网络游戏服务器陷入死循环的处理方法,首先检测死循环,当判定主线程陷入死循环后,监护线程就将主线程挂起,使它暂时停止运行。在主线程的Lua语言程序陷入死循环后,通过监护线程的处理,主动触发Lua的运行时错误,让它中止运行,然后跳回到C/C++里,这样就从死循环中解脱出来,然后通过一些后续处理,来避免再运行相同的代码,从而避免再次陷入死循环。本发明提供一种稳定有效的网络游戏服务器陷入死循环后的处理方法。
Description
【技术领域】
本发明属于计算机软件技术领域,具体是指一种使用脚本的网络游戏服务器陷入死循环的处理方法。
【背景技术】
在软件架构里,很基本的一个模式就是Client/Server模式,Client端用于显示数据和响应操作,而Server负责为所有的Client端服务器:下发数据和响应上发的消息。网络游戏的实现也是这样一种典型的架构,Client端就是游戏客户端,玩家在客户端显示的虚拟世界里进行游戏,而Server端就是游戏服务器,负责下发玩家的信息和同步其它的玩家。
如果游戏服务器代码有问题,程序运行过程中出现死循环,那它就再也不能处理客户端的连接和消息包,所有的客户端就都不能进行游戏了。这对几千人、几万人在线的游戏来讲是致命的。目前游戏行业的服务器,都是通过提高代码质量、大量进行测试来防止出现死循环,而一旦出现死循环,就只能重启服务器程序了。而维护服务器的人不可能一天24小时就呆在服务器旁边,所以经常发生服务器出问题后,过了好久才将服务器重启的情况。这给游戏的运营,带来了很不好的影响。
有鉴于此,本发明人针对现有技术的缺陷深入研究,遂有本案产生。
【发明内容】
本发明所要解决的技术问题在于提供一种稳定有效的网络游戏服务器陷入死循环的处理方法。
本发明是这样实现的:
网络游戏服务器陷入死循环的处理方法,包括如下步骤:
第一步骤:死循环的检测:
在主线程处理消息前,将这个消息的唯一id、类型和当前时刻记录下来,保存在一个可多线程访问的结构类型的数据里,然后调入到Lua里对这个消息进行处理,处理完后回到C++里时,再将这些信息清空;监护线程以固定的频率来检测这些信息的处理情况,不同的消息通过消息的唯一id来标识,如果每次检测时,发现都是在同一个消息的处理状态中,并且处理时间已经超过了最大值,那么就判断陷入了死循环;
第二步骤:死循环的恢复:
当判定主线程陷入死循环后,监护线程就将主线程挂起,使它暂时停止运行,然后取得Lua实例,就是lua_State对象,然后通过Lua库的接口,取得当前的运行堆栈,记录到日志中,方便查出到底是哪里的代码引起了死循环;然后取得Lua实例中的_G全局变量,将_G这个table中的所有变量和函数,移到另外一个新建的table,清空_G变量里的数据;然后监护线程将主线程设置为进入“Lua死循环错误状态”,然后再恢复主线程的运行,当主线程里的Lua代码访问到_G里的变量或函数,会触发Lua错误,就会跳回到C++里,主线程就成功地从死循环中跳出来了;跳回到C++里后,检测到当前是“Lua死循环错误状态”,就将Lua中的_G_BACKUP存储的变量和函数取出,设置回_G全局变量中,就恢复了Lua的正常运行环境。
进一步地,所述监护线程将Lua实例中的_G变量清空的同时,会记录下当前处理的消息类型,然后当主线程恢复到正常运行状态时,如果有客户端又上发了这个类型的消息,服务器将会丢弃这个消息而不再处理。
本发明的优点在于:这是一种比较通用的主动使脚本语言触发运行错误的方法,只要一个脚本语言有一个类似Lua里的_G全局表的变量,就可以使用这种方法。使用这个方法后,服务器再也没有发生过陷入死循环后,所有玩家都不能进行游戏的事情了,服务器更加稳定,不用担心服务器忽然在什么时候又出问题了。
【具体实施方式】
程序一旦陷入死循环,基本上无法恢复,除非重启进程,特别是像C/C++这样的中低级语言开发的程序。游戏服务器由于逻辑比较复杂,所以一般会接入脚本进行开发,本发明项目里使用的就是Lua脚本。除了框架代码,所有的游戏逻辑功能,都使用Lua语言开发。Lua这样的脚本语言有一个特征,就是运行时如果发生错误,会跳到从C/C++调到Lua的初始地方,而不是像C/C++那样,遇到运行错误程序就直接崩溃退出了。本发明技术方案的核心思想,就是在Lua语言程序陷入死循环后,主动触发它的运行时错误,让它中止运行,然后跳回到C/C++里,这样就从死循环中解脱出来,然后通过一些后续处理,来避免再运行相同的代码,从而避免再次陷入死循环。
本发明共涉及到两个线程,一个线程就是游戏服务器的主线程,负责处理所有客户端的消息,另一个线程起监视和协助的作用。
具体实现方式如下:
一、对死循环的检测:
在主线程处理消息前,将这个消息的唯一id、类型和当前时刻记录下来,保存在一个可多线程访问的结构类型的数据里,然后调入到Lua里对这个消息进行处理,处理完后回到C++里时,再将这些信息清空,表示已经完成了对这个消息的处理。如果在Lua语言里,对这个消息的处理过程中,陷入了死循环,那将不能正常地回到C++里,这时这些信息就会一直保持调入到Lua前的状态。另外一个线程,就是监护线程,以固定的频率(比如1分钟一次),来检测这些信息的处理情况,不同的消息通过消息的唯一id来标识,如果每次检测时,发现都是在同一个消息的处理状态中,并且处理时间已经超过了最大值,那么就判断陷入了死循环,然后就启动对死循环的恢复操作。对应的部分伪代码如下:
二、对死循环的恢复:
当判定主线程陷入死循环后,监护线程就将主线程挂起(比如使用windows的SuspendThread()函数),使它暂时停止运行,然后取得Lua实例,就是lua_State对象,然后通过Lua库的接口,取得当前的运行堆栈,记录到日志中,方便查出到底是哪里的代码引起了死循环。然后取得Lua实例中的_G全局变量,它是一个语言本身自带的table类型的变量,里面存储着几乎所有Lua程序运行需要的变量和函数。将_G这个table中的所有变量和函数,移到另外一个新建的table(比如叫_G_BACKUP)中,然后清空_G变量里的数据。然后监护线程将主线程设置为进入“Lua死循环错误状态”,然后再恢复主线程的运行,这时由于_G变量已经被清空,那主线程里的Lua代码只要访问到_G里的变量或函数,就等于访问了nil变量,就会触发Lua错误,就会跳回到C++里。这样主线程就成功地从死循环中跳出来了。跳回到C++里后,检测到当前是“Lua死循环错误状态”,就将Lua中的_G_BACKUP存储的变量和函数取出,设置回_G全局变量中,这样就恢复了Lua的正常运行环境。然后服务器继续它的正常运行:接收客户端发来的消息、进行处理然后返回消息。
清空_G变量,之所以能有效地使Lua发生运行错误,是因为在Lua语言里,除了局部变量和函数,其它几乎所有的变量和函数,都直接或间接在保存在_G这个巨大的table类型的数据里。只要不是在一个函数中,使用像这样的代码造成的死循环:for i=1,n do end,这样简单在代码在实际项目中几乎不可能存在,发生死循环的代码一般是比较复杂的逻辑造成的。除了这种情况,其它的代码基本上都会访问到_G变量,比如这样写的循环:for k,vinpairs(t)do end,这行代码中pairs就是存储在_G中的全局变量,还有包括所有的字符串处理函数、table处理函数和游戏里自定义的界面类、逻辑类、消息类等,都需要直接或间接在存储在_G这个变量中,它是语言的运行依赖环境。所以只要清空了_G变量,Lua在运行时,就会触发Lua错误了。
这是一种比较通用的主动使脚本语言触发运行错误的方法,只要一个脚本语言有一个类似Lua里的_G全局表的变量,就可以使用这种方法。还有一种是利用Lua语言本身有提供的函数:lua_sethook(),监护线程通用调用这个函数,可以设置一个钩子函数,然后主线程在恢复运行后,只要执行一行代码、进入一个函数或退出一个函数时,就会自动调用这个钩子函数,然后在这个函数里,只需要调用luaL_error()就可以主动触发Lua错误而跳回到C++里。这个方法实现起来更方便一些,但只对Lua语言有效。本专利替换全局表的方法,所有类型的脚本语言都可以使用。
三、对死循环的预防:
从死循环中跳出后,如何防止服务器执行相同的代码而再次陷入死循环呢?在上一部分,监护线程将Lua实例中的_G变量清空的同时,会记录下当前处理的消息类型,然后当主线程恢复到正常运行状态时,如果有客户端又上发了这个类型的消息,服务器将会丢弃这个消息而不再处理。这样就避免了服务器再次执行到相同的代码而陷入死循环。这样做虽然会使某些客户端的部分功能不正常,但比服务器出错,所有的客户端都不能玩游戏要好得多。
使用这个方法后,服务器再也没有发生过陷入死循环后,所有玩家都不能进行游戏的事情了。服务器更加稳定,不用担心服务器忽然在什么时候又出问题了。
不仅网络游戏服务器可以使用这个方法,所有其它类型的有使用脚本的服务器,都可以应用该技术。甚至只要是有应用脚本的程序,如果有处理死循环的需要,都可以应用这个技术。
以上所述仅为本发明的较佳实施用例而已,并非用于限定本发明的保护范围。凡在本发明的精神和原则之内,所作的任何修改、等同替换以及改进等,均应包含在本发明的保护范围之内。
Claims (2)
1.网络游戏服务器陷入死循环的处理方法,其特征在于:包括如下步骤:
第一步骤:死循环的检测:
在主线程处理消息前,将这些消息的每一个唯一id、类型和当前时刻记录下来,保存在一个可多线程访问的结构类型的数据里,然后调入到Lua脚本程序里对这些消息进行处理,处理完后回到C++程序里时,再将这些消息清空;监护线程以固定的频率来检测这些消息的处理情况,不同的消息通过消息的唯一id来标识,如果每次检测时,发现都是在同一个消息的处理状态中,并且处理时间已经超过了最大值,那么就判断Lua脚本程序陷入了死循环,并因此间接导致主程序陷入死循环;
第二步骤:死循环的恢复:
当判定主线程陷入死循环后,监护线程就将主线程挂起,使它暂时停止运行,然后取得Lua脚本程序实例,就是lua_State对象,然后通过Lua脚本程序库的接口,取得当前的运行堆栈,记录到日志中,方便查出到底是哪里的代码引起了死循环;然后取得Lua脚本程序实例中的_G全局变量,将_G这个table中的所有变量和函数,移到另外一个新建的table,清空_G变量里的数据;然后监护线程将主线程设置为进入“Lua脚本程序死循环错误状态”,然后再恢复主线程的运行,当主线程里的Lua脚本程序代码访问到_G里的变量或函数,会触发Lua错误,就会跳回到C++程序里,主线程就成功地从死循环中跳出来了;跳回到C++程序里后,检测到当前是“Lua脚本程序死循环错误状态”,就将Lua脚本程序中的_G_BACKUP存储的变量和函数取出,设置回_G全局变量中,就恢复了Lua脚本程序的正常运行环境。
2.如权利要求1所述的网络游戏服务器陷入死循环的处理方法,其特征在于:
所述监护线程将Lua脚本程序实例中的_G变量清空的同时,会记录下当前处理的消息类型,然后当主线程恢复到正常运行状态时,如果有客户端又上发了这个类型的消息,服务器将会丢弃这个消息而不再处理。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201410050333.5A CN103810053B (zh) | 2014-02-14 | 2014-02-14 | 网络游戏服务器陷入死循环的处理方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201410050333.5A CN103810053B (zh) | 2014-02-14 | 2014-02-14 | 网络游戏服务器陷入死循环的处理方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN103810053A CN103810053A (zh) | 2014-05-21 |
CN103810053B true CN103810053B (zh) | 2017-06-13 |
Family
ID=50706860
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201410050333.5A Active CN103810053B (zh) | 2014-02-14 | 2014-02-14 | 网络游戏服务器陷入死循环的处理方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN103810053B (zh) |
Families Citing this family (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN106484507B (zh) * | 2016-09-18 | 2019-11-29 | 天脉聚源(北京)传媒科技有限公司 | 一种应用线程的处理方法及装置 |
CN107562516A (zh) * | 2017-08-07 | 2018-01-09 | 北京金山安全管理系统技术有限公司 | 多线程处理方法和装置、存储介质及处理器 |
CN112134755A (zh) * | 2020-09-21 | 2020-12-25 | 杭州迪普科技股份有限公司 | 公共网关接口程序监测方法及装置 |
CN114610643B (zh) * | 2022-03-23 | 2022-11-15 | 一点灵犀信息技术(广州)有限公司 | 代码性能检测方法、装置和电子设备 |
Citations (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB2336919A (en) * | 1998-04-30 | 1999-11-03 | Ibm | Pre-emptive threading in a virtual machine |
JP2005182594A (ja) * | 2003-12-22 | 2005-07-07 | Matsushita Electric Ind Co Ltd | コンピュータ及びプログラム |
JP2008204013A (ja) * | 2007-02-16 | 2008-09-04 | Seiko Epson Corp | スレッド動作異常検知方法、マルチスレッドシステム |
CN102207879A (zh) * | 2011-06-14 | 2011-10-05 | 贵阳朗玛信息技术股份有限公司 | Lua脚本热更新方法及系统 |
CN103019697A (zh) * | 2012-11-22 | 2013-04-03 | 福建天晴数码有限公司 | 一种lua脚本的编辑插件 |
CN103345422A (zh) * | 2013-07-02 | 2013-10-09 | 厦门雅迅网络股份有限公司 | 一种基于Linux的多线程硬实时控制方法 |
CN103399818A (zh) * | 2013-08-13 | 2013-11-20 | 中国科学技术大学苏州研究院 | 操作系统中的死锁检测方法 |
-
2014
- 2014-02-14 CN CN201410050333.5A patent/CN103810053B/zh active Active
Patent Citations (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB2336919A (en) * | 1998-04-30 | 1999-11-03 | Ibm | Pre-emptive threading in a virtual machine |
JP2005182594A (ja) * | 2003-12-22 | 2005-07-07 | Matsushita Electric Ind Co Ltd | コンピュータ及びプログラム |
JP2008204013A (ja) * | 2007-02-16 | 2008-09-04 | Seiko Epson Corp | スレッド動作異常検知方法、マルチスレッドシステム |
CN102207879A (zh) * | 2011-06-14 | 2011-10-05 | 贵阳朗玛信息技术股份有限公司 | Lua脚本热更新方法及系统 |
CN103019697A (zh) * | 2012-11-22 | 2013-04-03 | 福建天晴数码有限公司 | 一种lua脚本的编辑插件 |
CN103345422A (zh) * | 2013-07-02 | 2013-10-09 | 厦门雅迅网络股份有限公司 | 一种基于Linux的多线程硬实时控制方法 |
CN103399818A (zh) * | 2013-08-13 | 2013-11-20 | 中国科学技术大学苏州研究院 | 操作系统中的死锁检测方法 |
Also Published As
Publication number | Publication date |
---|---|
CN103810053A (zh) | 2014-05-21 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN103810053B (zh) | 网络游戏服务器陷入死循环的处理方法 | |
CN107158705B (zh) | 服务的更新方法和装置 | |
US10013553B2 (en) | Protecting software application | |
US10901810B2 (en) | Event-based record and replay for advanced applications | |
US9471461B2 (en) | Guarding a monitoring scope and interpreting partial control flow context | |
US20070143766A1 (en) | Deadlock detection in a computing environment | |
CN110147269B (zh) | 一种事件处理方法、装置、设备及存储介质 | |
US20140033181A1 (en) | Reverse debugging | |
CN105590063B (zh) | 一种挖掘漏洞的方法、装置及电子设备 | |
US8458336B2 (en) | State machine event restoration | |
CN105512562B (zh) | 一种漏洞挖掘方法、装置及电子设备 | |
CN103839007A (zh) | 一种检测异常线程的方法及系统 | |
CN107742077B (zh) | 一种在游戏直播中防止信息泄露的方法及装置 | |
CN108845875A (zh) | 一种常驻进程保活系统以及方法 | |
CN111524007A (zh) | 一种智能合约的嵌入式入侵检测方法及装置 | |
EP2713277B1 (en) | Latent defect identification | |
Jiang et al. | Simplydroid: efficient event sequence simplification for android application | |
CN108804920A (zh) | 一种基于跨进程行为监控恶意代码同源性分析的方法 | |
CN117180750A (zh) | 基于行为树的非用户角色控制方法、装置、设备及介质 | |
CN110602027B (zh) | 游戏的自动控制方法和装置 | |
CN107305507A (zh) | 死锁控制方法和装置 | |
Lewis et al. | Repairing games at runtime or, how we learned to stop worrying and love emergence | |
CN109033821A (zh) | 一种栈溢出攻击防护系统及方法 | |
CN113157377B (zh) | 一种Android系统实现对应用部分管控的方法及设备 | |
CN104516791B (zh) | 数据处理方法、装置及电子设备 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |