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?
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:So to correctly handle killing a child process one need to follow: