Starting a process and killing it from a Ruby on Rails application without leaving the zombie process
I am developing a Ruby on Rails application. Part of the functionality is to start and close the serial communication with the Modbus slave device, receive data and store it in a 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 in Ruby.
My idea is to start a process that will execute the python script and kill the process when it is no longer needed.
I start a process like this, so I can access it pid:
def start
...
@@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid
...
@@ pids is a hash that stores all initial processes keyed as object.id (assuming each object can only start one process)
When I want to close the connection, I kill the process like this:
def stop
...
pid = @@pids[ object.id ]
system("kill #{pid}")
This leads to the zombie process (visible after ps aux | grep python
):
[python] <defunct>
I tried to send a signal SIGCHLD
to the rails app (as it is the parent of the previously named python script) but it doesn't work.
I want to add that I may need to call / kill this process quite often so that it can lead to a huge number of zombie processes.
How can I kill a process without leaving the zombie process?
source to share
The problem is not in the python script - signals are handled by default (no change after module implementation signal
).
The problem is with the ruby script. After killing a process, its parent server (the server in this case) must somehow know that it was killed. There is a function for this wait
. From ruby documentation:
The parent process must use Process.wait to collect the completion status of its child
So, to properly handle killing a child process, you need to follow:
def stop
...
pid = @@pids[ object.id ]
Process.kill( 15, pid )
Process.wait( pid )
...
source to share