[ANN] Terminator 0.4.4

Discussion in 'Ruby' started by Mikel Lindsaar, Sep 21, 2008.

  1. 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://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 -
    mikel lindsaar -

    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
     
    Mikel Lindsaar, Sep 21, 2008
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mack Attack
    Replies:
    3
    Views:
    6,975
    Roedy Green
    Aug 8, 2003
  2. David Hirschfield

    Help: asyncore/asynchat and terminator string

    David Hirschfield, Jan 16, 2007, in forum: Python
    Replies:
    0
    Views:
    342
    David Hirschfield
    Jan 16, 2007
  3. semut
    Replies:
    3
    Views:
    413
    Binary
    Dec 1, 2006
  4. dbtouch
    Replies:
    32
    Views:
    3,346
    Jerry Coffin
    Mar 8, 2009
  5. ara howard

    [ANN] terminator-0.4.2

    ara howard, Sep 10, 2008, in forum: Ruby
    Replies:
    0
    Views:
    110
    ara howard
    Sep 10, 2008
Loading...

Share This Page