Starting a process and killing it from Ruby on Rai

2019-02-24 22:48发布

I am developing a Ruby on Rails application. Part of the functionality is starting and closing connection with Modbus slave via serial port, getting data and storing it into database. Also I made a script in python that does exactly what I need so I don't want to reinvent the wheel and rewrite it into Ruby.

My idea is to start a process which will execute python script and kill the process whenever it is not needed anymore.

I start the process as follows, so I can access it's pid:

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

@@pids is a hash which stores all started processes' pids with key as object.id (presumption is that each object can start only one process)

When I want to close the connection I kill the process like:

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

This results in zombie process (visible after ps aux | grep python):

[python] <defunct>

I tried to send SIGCHLD signal to rails application (as it is parent of earlier called python script) but it doesn't work.

I want to add that I might need to call/kill this process quite often so it can result in huge amount of zombie processes.

How can I kill a process without leaving zombie process behind?

1条回答
地球回转人心会变
2楼-- · 2019-02-24 23:01

Problem was not in the python script - signals are handled properly by default (no change after implementing signal module).

The issue is in the ruby script. After killing a process, its parent (rails server in this case) needs to know somehow that it was killed. For this purpose there is a wait function. From ruby documentation:

The parent process should use Process.wait to collect the termination status of its child

So to correctly handle killing a child process one need to follow:

def stop
    ...
    pid = @@pids[ object.id ]
    Process.kill( 15, pid )
    Process.wait( pid )
    ...
查看更多
登录 后发表回答