Bootstrap

欣赏一个尚未关闭的python运行时bug

这是一个语言的运行时错误,在linux环境,跨语言使用共享内存时,会触发。它会在python程序退出时,自行销毁sharedMemory,即便此时还有其他的进程在使用——这会让C/Python跨进程调用几乎没有办法进行。

python程序运行完毕会弹出错误信息:

UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown

然后你定义的sharedMemory就被python随手析构了。如果涉及C调用python,与共享内存相关的数据只能读,无法从python传出——因为python会析构它。共享内存本来就是为了在进程间高效传递二进制参数和运算结果的——这个bug会这类跨进程协同的设计无法进行。

python语言维护群组,对这个问题的相关原始讨论参见下面代码中的注释中的那个链接地址。现有的python发行版本中还没有消除这个bug——因为有一些其他的关联考量。我拷贝了一份github的快照,有兴趣的同学可以读读看,这是我职业生涯中遭遇的第二处runtime lib bug,至少在2019年已经有人报告,它居然还没有正式修复(截止2024/5/15)。。。 

然后,更奇妙的是使用python的monkey patch,用户可以自行封堵住这个bug。下面是github讨论中提到的补丁:

# 使用monkeypatch给python代码打补丁:
# 解决python程序在退出时自动销毁关联的sharedmemory的bug.
# 只需要在你的python应用程序启动时,调用:patch_ban_shm_tracing()就可以封堵住这个bug.
#
# 相关原始信息:
#     https://github.com/python/cpython/issues/82300

from multiprocessing import resource_tracker
 
def fix_register(name, rtype):
    if rtype == "shared_memory":
        return
    return resource_tracker._resource_tracker.register(self, name, rtype)
 
def fix_unregister(name, rtype):
    if rtype == "shared_memory":
        return
    return resource_tracker._resource_tracker.unregister(self, name, rtype)
 
def patch_ban_shm_tracing():
    resource_tracker.register = fix_register
    resource_tracker.unregister = fix_unregister
    if "shared_memory" in resource_tracker._CLEANUP_FUNCS:
        del resource_tracker._CLEANUP_FUNCS["shared_memory"]
 

这是一个很好的切入点,大家可以看看python语言本身的维护策略。开源环境,似乎类似的问题我们可以看到很多,比如:

上面是cJson.c的一处原生注释...对技术领域的文艺青年, 探查这些注释,帖子,比对开源源代码间的差异,发掘相关的故事,其实是很好的素材。

技术问题的暴露和最终的解决,所涉及的权衡,对大多数人来说,也是足够好的经验习得来源。它们可以向我们展示正确的设计该是什么样的。

created at May15,2024(zz)

;