1

I have Ruby programA that calls Ruby programB with:

 system("ruby programB.rb <parameters>")

Under certain conditions, I want programB to terminate its operation (and the associated subshell) but allow programA to continue on to the next set of parameters.

However, exit() and abort() kill both the subshell and the parent, and I am unable to get Process.kill("SIGTERM",0) to work in programB (unfortunately, this is on Windows). I'm running ruby 1.9.2.

How can I terminate programB without also killing programA?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
JESii
  • 4,678
  • 2
  • 39
  • 44

3 Answers3

3

If the regular system call isn't cutting it, the usual way is to do something like this:

pid = fork do
  exec("ruby programB.rb ...")
end

kill("SIGTERM", pid)

The fork operation gives you a process identifier you can kill. system will block until the child process returns, so any call to kill in the parent process will affect only the parent process.

Unfortunately there's no fork in Windows, but there are alternatives that achieve the same thing.

Community
  • 1
  • 1
tadman
  • 208,517
  • 23
  • 234
  • 262
  • Thanks for the pointer to alternatives for Windows; I've made a note of that for the future. – JESii Dec 22 '12 at 17:05
2

exit() and abort() don't kill the parent, at least not on Mac OS, and Linux in my experience.

Try saving this as abort.rb:

puts RUBY_VERSION
puts `date`
puts 'aborting'
abort

and this as exit.rb:

puts RUBY_VERSION
puts `date`
puts 'exiting'
exit

Then save this as test.rb in the same directory and run it:

puts `ruby exit.rb`
puts `ruby abort.rb`

On my system I see:

1.9.3
Fri Dec 21 22:17:12 MST 2012
exiting
1.9.3
Fri Dec 21 22:17:12 MST 2012
aborting

They do exit the currently running script in the sub-shell, which then exits because it's not a log-in shell, and could set a return status which is important to the calling program, but I have yet to see them kill the parent.

If you need to capture STDERR, using backticks or %x won't work. I'd recommend using Open3.capture3 for simplicity if you need to know what status code was returned, or whether STDERR returned anything.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • FYI, I needed `date /t` for windows, but other than that it worked as you expected, so I went back to go over my code yet again. Finally found a typo '\' instead of '|' which solved the problem. Thanks! – JESii Dec 22 '12 at 17:06
0

The only thing that works reliably for me is this:

kill -INT $$

It reliably kills the script and only the script, even if it was source'd from the command line. Note that I'm running GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin15.6.0); I can't recall if this works on bash 3.x

JESii
  • 4,678
  • 2
  • 39
  • 44