客户端服务在主机崩溃和 SIGKILL 事件发生时仍能正常运行(注册表仅存储在内存中,没有启动清理程序)
现在,#3812:信号处理程序、`POST /api/system/shutdown` 和 `stop()` 都会进入 `runShutdown`,该函数在退出之前会停止客户机。剩下的就是永远无法运行其关机程序的主机。SIGKILL、OOM kill、电源故障或内核崩溃会导致客户机服务在没有父进程的情况下继续运行。`lib/guests/service.js` 将其运行时存储在模块级别的 Map 中,没有 pid 文件和磁盘记录,因此下次启动时没有可找到的内容,也无需清理。这个问题比漂浮进程更为严重。允许的服务没有沙箱,并且以用户的完全访问权限运行(见 `lib/guests/DOCUMENTATION.md`),因此每个孤儿都会无限期地保留回环端口和授权的套接字,直到机器重新启动或有人手动杀死它。来自一个守护进程主机的字段数据:每天大约有 11 个孤儿,每个大约 22-56 MB。我认为修复方法是 OpenCode 回收工具已经在 `lib/opencode/managed-process-registry.js` 中使用的模式:记录我们创建的 pid,在启动时运行回收工具,并在杀死之前重新验证身份。客户机在其环境中携带了主机生成的 `OPENCHAMBER_SERVICE_TOKEN`,因此可以在杀死之前从环境中检查身份,此外,在 Unix 上,`PPid == 1` 可以确认所有者已消失。有两个设计限制需要提前解决。Linux 只支持 `/proc/<pid>/environ`,因此 macOS 需要使用 `ps`,Windows 需要使用 `tasklist`;Windows 还没有重新父进程为 1 的语义,OpenCode 回收工具已经通过要求记录的所有者 pid 必须已死亡来解决了这个问题。此外,多个窗口和主机同时运行,因此记录必须是每个创建的进程一个文件,而不是共享文件,原因是 OpenCode 记录器的布局方式也是如此。还有一个相同所有者的较小差距:在客户机停止和 HTTP 监听器在关闭期间的客户机请求之间,可以重新创建服务并使其孤立。
内容来源: openchamber/openchamber