启动一个进程并从Ruby on Rails应用程序中删除它而不会离开僵尸进程

时间:2015-04-24 11:01:24

标签: python ruby-on-rails ruby linux zombie-process

我正在开发Ruby on Rails应用程序。部分功能是通过串口启动和关闭与Modbus从站的连接,获取数据并将其存储到数据库中。我也在python中创建了一个完全符合我需要的脚本,所以我不想重新发明轮子并将其重写为Ruby。

我的想法是启动一个执行python脚本的进程,并在不再需要时终止进程。

我按照以下步骤开始,所以我可以访问它的pid:

def start
    ...
    @@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid
    ...

@@ pids是一个哈希,它存储所有已启动的进程'密钥为object.id的pids(假设每个对象只能启动一个进程)

当我想要关闭连接时,我会杀死这个过程:

def stop
    ...
    pid = @@pids[ object.id ]
    system("kill #{pid}")

这导致僵尸进程(在ps aux | grep python之后可见):

[python] <defunct>

我尝试将SIGCHLD信号发送到rails应用程序(因为它是之前调用的python脚本的父代),但它不起作用。

我想补充一点,我可能需要经常调用/终止这个过程,这样会导致大量的僵尸进程。

如何在不离开僵尸进程的情况下杀死进程?

1 个答案:

答案 0 :(得分:1)

python脚本中没有问题 - 默认情况下信号处理正确(实现signal模块后没有变化)。

问题出在ruby脚本中。杀死一个进程后,它的父进程(在这种情况下为rails服务器)需要知道它被杀死了。为此,有一个wait函数。来自ruby文档:

  

父进程应使用Process.wait来收集其子进程的终止状态

因此要正确处理杀死子进程,需要遵循:

def stop
    ...
    pid = @@pids[ object.id ]
    Process.kill( 15, pid )
    Process.wait( pid )
    ...