# Terminator 0.4.4

**URL:** <https://www.ruby-forum.com/t/terminator-0-4-4/149128>\
**Category:** Ruby\
**Created:** [September 21, 2008, 3:50am UTC](https://www.ruby-forum.com/t/terminator-0-4-4/149128 "2008-09-21T03:50:59Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mikel\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/2bfe46/32.png) [@Mikel\_L](https://www.ruby-forum.com/u/Mikel_L)\
**Post date:** [September 21, 2008, 3:50am UTC](https://www.ruby-forum.com/t/terminator-0-4-4/149128/1 "2008-09-21T03:50:59Z")

</div>

NAME  
Terminator

SYNOPSIS  
An external timeout mechanism based on processes and signals. Safe  
for  
system calls. Safe for minors. but not very safe for misbehaving,  
downtrodden zombied out processes.

CHANGES  
Major change since 0.4.2 was making Terminator loop safe, that is, you  
can  
now run Terminator inside a loop without getting conflicts. Also  
added RDoc  
and more specs.

DESCRIPTION  
Terminator is a solution to the problem of ‘how am I meant to kill a  
system call in Ruby!?’

Ruby (at least MRI) uses green threads to “multitask”. This means  
that  
there is really only ever one ruby process running which then splits  
up  
it’s processor time between all of it’s threads internally.

The processor then only has to deal with one ruby process and the ruby  
process deals with all it’s threads. There are pros and cons to this  
method, but that is not the point of this library.

The point is, that if you make a system call to an external resource  
from  
ruby, then the kernel will go and make that call for ruby and NOT COME  
BACK  
to ruby until that system call completes or fails. This can take a  
very  
long time and is why your feeble attempts at using ruby’s internal  
“Timeout”  
command has failed miserably at timing out your external web service,  
database  
or network connections.

You see, Ruby just doesn’t get a chance to do anything as the kernel  
goes  
“I’m not going to talk to you again until your system calls complete”.  
Sort  
of a no win situation for Ruby.

That’s where Terminator comes in. Like Arnie, he will come back. No  
matter  
what, and complete his mission, unless he gets aborted before his  
timeout,  
you can trust Terminator to thoroughly and without remorse, nuke your  
misbehaving and timing out ruby processes efficiently, and quickly.

HOW IT WORKS  
Basically we create a new terminator ruby process, separate to the  
existing  
running ruby process that has a simple command of sleep for x  
seconds, and then  
do a process TERM on the PID of the original ruby process that created  
it.

If your process finishes before the timeout, it will kill the  
Terminator first.

So really it is a race of who is going to win?

Word of warning though. Terminator is not subtle. Don’t expect it to  
split  
hairs. Trying to give a process that takes about 1 second to  
complete, a  
2 second terminator… well… odds are 50/50 on who is going to make  
it.

If you have a 1 second process, give it 3 seconds to complete. Arnie  
doesn’t  
much care for casualties of war.

Another word of warning, if using Terminator inside a loop, it is  
possible  
to exceed your open file limit. I have safely tested looping 1000  
times

INSTALL  
gem install terminator

URIS  
[http://codeforpeople.com/lib/ruby](http://codeforpeople.com/lib/ruby)  
[http://rubyforge.org/projects/codeforpeople](http://rubyforge.org/projects/codeforpeople)

HISTORY  
0.4.2  
\* initial version (ara)  
0.4.3  
\* added some extra specs and test cases and minor fixes (mikel)  
0.4.4  
\* made terminator loop safe. 1000.times { Terminator.timeout(1)  
do true; end }  
now works (mikel)  
\* added more test cases (mikel)  
\* added rdoc (mikel)

AUTHORS  
ara.t.howard - removed\_email\_address@domain.invalid  
mikel lindsaar - removed\_email\_address@domain.invalid

SAMPLES

\<========\< samples/a.rb \>========\>

~ \> cat samples/a.rb

```
require 'terminator'

Terminator.terminate 2 do
  sleep 4
end

```

~ \> ruby samples/a.rb

```
samples/a.rb:3: 2s (Terminator::Error)
  from samples/a.rb:3

```

\<========\< samples/b.rb \>========\>

~ \> cat samples/b.rb

```
require 'terminator'

Terminator.terminate 0.2 do
  sleep 0.4 rescue puts 'timed out!'
end

```

~ \> ruby samples/b.rb

```
timed out!

```

\<========\< samples/c.rb \>========\>

~ \> cat samples/c.rb

```
require 'terminator'

begin
  Terminator.terminate :seconds => 0.2 do
    sleep 0.4
  end
rescue Terminator.error
  puts 'timed out!'
end

```

~ \> ruby samples/c.rb

```
timed out!

```

\<========\< samples/d.rb \>========\>

~ \> cat samples/d.rb

```
require 'terminator'

trap = lambda{ puts "signaled @ #{ Time.now.to_i }" }

Terminator.terminate :seconds => 1, :trap => trap do
  sleep 2
  puts "woke up @ #{ Time.now.to_i }"
end

```

~ \> ruby samples/d.rb

```
signaled @ 1221026177
woke up @ 1221026178

```

\<========\< samples/e.rb \>========\>

~ \> cat samples/e.rb

```
require 'terminator'

puts "Looping 1000 times on the terminator..."
success = false
1.upto(1000) do |i|
  success = false
  Terminator.terminate(1) do
    success = true
  end
  print "\b\b\b#{i}"
end
puts "\nI was successful" if success

```

~ \> ruby samples/e.rb

```
Looping 1000 times on the terminator...
1000
I was successful

```
