Search code examples
rubypopenkill

Ruby force close IO.popen java process


How can I force quit/kill a java process that was stared with IO.popen("command", "r+")?

I am running a script a small java program from ruby doing the following:

pipe = IO.popen("nice -n 19 java -Xmx2g -Djava.awt.headless=true -jar java_program.jar", 'r+')

Then I use stdio to send arguments back and forth, like this:

pipe.puts "data"
result = pipe.gets

This works fine for most data I send, but for some the java process seems to lock up or something, and I would like to force close / kill the java process.

I am currently doing the following, which does not seem to kill the java process (from another thread which watches over this stuff):

thepid = nil
thepid = pipe.pid            if pipe.respond_to?(:pid)
pipe.puts('')                if pipe.respond_to?(:puts) #This is the java_program's approach to closing, writing empty string to stdio will cause it to start it's shutdown procedure.
pipe.close                   if pipe.respond_to?(:close)
Process.kill('KILL', thepid) if thepid && Process.getpgid( thepid )

The java process lingers and refuses to die. What can I do to actually force the process to exit (it uses lots of ram :( )

Also: Is there a cross platform way of doing this?


Solution

  • What you may be seeing here is that you're killing the nice process and not the java process it launches.

    You could avoid this by launching the java process directly and then altering the nice level using renice on the PID you get.

    It's also worth checking that you're trying to kill the correct process. As you point out, spawning a second instance by accident would mean you're killing the wrong one.

    A tool like popen3 allows for a lot more control over the child process and gives you the ability to feed input and capture output directly.