使用PyO3运行用户Python代码时如何避免无限循环阻塞服务器线程
可行实现方案
方案1:子进程隔离(最稳妥,无副作用)
直接给玩家脚本分配独立的子进程运行,完全和Rust主服务进程隔离,你可以对每个子进程做CPU、内存的资源配额限制,超时直接销毁整个进程即可,完全不会影响主服务稳定性。
具体实现可以预启动一个Python子进程池,按需分配空闲进程给玩家调用,执行on_event时Rust侧通过管道将事件数据传给子进程,同时启动超时计时器,超过设定阈值(比如100ms)直接kill对应子进程,再拉取新的空闲进程补入池子即可。即使大量玩家提交死循环脚本,也只会打满你给子进程池分配的固定配额CPU资源,不会无限占满服务器资源。方案2:字节码跟踪+超时抛出(轻量,同进程低开销)
如果可以接受同进程运行,你可以利用Python内置的sys.settrace()接口注入跟踪钩子,在玩家脚本执行前先注册自定义跟踪函数,每执行N行Python字节码就检查一次运行时长,超过阈值直接抛异常终止执行。
这种方案性能开销极低,只要限制玩家不能导入C扩展模块,即可拦截所有纯Python实现的死循环。你可以在PyO3调用玩家函数之前,先在当前Python解释器环境中注入该跟踪逻辑,执行结束后再卸载钩子即可,不会影响其他代码运行。方案3:独立解释器+跟踪逻辑(隔离性和性能折中)
你可以用PyO3的PyInterpreterConfig为每个玩家创建独立的Python解释器实例,不同解释器之间资源完全隔离,不会出现变量、模块泄露的安全问题。再配合方案2的字节码跟踪逻辑,即可在实现资源隔离的同时控制执行超时,开销比子进程低,隔离性比单解释器多线程方案好。
所有方案都需要提前禁用Python的危险模块导入权限,禁止玩家调用
os、subprocess、socket等底层接口,避免出现安全漏洞。
内容的提问来源于stack exchange,提问作者LightningdeGolem
相关产品推荐
相关产品推荐

