Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS 

Kill Ruby code which takes too long for normal execution

Source: Terminator - Timeout without Mercy [lindsaar.net] via rubyflow.com

gem install terminator

   1  
   2  require 'rubygems'
   3  require 'terminator'

   1  
   2  irb(main):008:0* Terminator.terminate 3 do
   3  irb(main):009:1*   sleep 2
   4  irb(main):010:1>   puts "I will print"
   5  irb(main):011:1> end
   6  I will print
   7  => nil
   8  irb(main):012:0> 
   9  irb(main):013:0* Terminated


The irb session is then also terminated.

   1  
   2  irb(main):003:0> Terminator.terminate 1 do
   3  irb(main):004:1*   sleep 2
   4  irb(main):005:1>   puts "I'll never print"
   5  irb(main):006:1> end
   6  Terminator::Error: 1s
   7  	from (irb):3
   8  	from (irb):3
   9  irb(main):007:0> 


The irb session remains active.

I tried running the script from a file however it still terminated the script prematurely if the Terminator condition was true. Here's a script I've found works for me:

   1  #!/usr/bin/ruby
   2  # file: test-terminator.rb
   3  
   4  require 'rubygems'
   5  require 'terminator'
   6  
   7  class Class
   8    def unsafe_methods(*methods)
   9      methods.each do |method|
  10        self.class_eval "def safe_and_#{method}; sandbox('#{method}'); end;"
  11      end
  12    end
  13  end
  14  
  15  
  16  class JustAClass
  17  
  18    def initialize()
  19    end
  20  
  21    unsafe_methods :slow, :normal
  22  
  23    def slow()
  24      result = ''
  25      Terminator.terminate 1 do
  26        sleep 2
  27        result =  "I'll never print"
  28      end
  29      result
  30    end
  31  
  32    def normal()
  33      result = ''
  34      Terminator.terminate 3 do
  35        sleep 2
  36        result = "I will print"
  37      end
  38      result
  39    end
  40  
  41    def method123()
  42      "well tested with local method calls which never really causes a problem"
  43    end
  44  
  45    def sandbox(statement)
  46      msg = `ruby -e "require 'test-terminator'; jac = JustAClass.new; puts jac.#{statement}"`
  47      msg
  48    end
  49  end
  50  
  51  if __FILE__ == $0 then
  52  
  53    jac = JustAClass.new
  54  
  55    #jac.slow()         # <-  1) this code would raise a terminator error 
  56                        #     and then terminate the script
  57  
  58    #puts jac.normal()  # <-  2) this code runs fine up until the  
  59                        #      the 3 seconds has expired at which point 
  60                        #      the script is terminated with the 
  61                        #      message 'Terminated'
  62  
  63    #puts jac.safe_and_slow()   # <- 3) executes method slow() and 
  64                                #       continues exectution
  65  
  66    puts jac.safe_and_normal()  # <- 4) executes method normal() and 
  67                                #       continues exectution
  68  
  69    puts jac.method123()        # <- a regular method which is relatively safe
  70  
  71    puts 'now sleeping for 3 seconds'
  72    sleep 3
  73    puts 'normal code execution can continue'
  74  end

output:

1) jac.slow()
=> ./test-terminator.rb:25:in `slow': 1s (Terminator::Error)
from ./test-terminator.rb:25

2) jac.normal()
=> I will print
well tested with local method calls which never really causes a problem
now sleeping for 3 seconds
Terminated

3) jac.safe_and_slow()
=> ./test-terminator.rb:25:in `slow': 1s (Terminator::Error)
from ./test-terminator.rb:25

well tested with local method calls which never really causes a problem
now sleeping for 3 seconds
normal code execution can continue

4) jac.safe_and_normal()
=>I will print
well tested with local method calls which never really causes a problem
now sleeping for 3 seconds
normal code execution can continue

You might be wondering why we need to manually create a ruby process surely we could just launch a new process with Thread.new right? Wrong if you read more about Ruby processes from the article Terminator - Timeout without Mercy [lindsaar.net] you will be reminded that Green threads are launched from a single Ruby process.

Is site down script

// Tests if site is down/server is offline by trying to connect in specified time

   1  
   2  import socket
   3  import urllib2
   4  
   5  def timeout(site, timeout):
   6    save = socket.getdefaulttimeout() 
   7    try:
   8      response = urllib2.urlopen(site)
   9      socket.setdefaulttimeout(save)
  10    except urllib2.URLError, err:
  11      socket.setdefaulttimeout(save)
  12      if err.__class__.__name__ == "URLError":
  13        if isinstance(err[0], socket.timeout):
  14          return True
  15    return False
  16  
  17  
  18  if timeout("http://www.dummy-site.com/test_timeout.html", 10):
  19    print "Timeout detected"

Mobile timeout app

   1  
   2  from appuifw import *
   3  from key_codes import *
   4  from graphics import Image
   5  from audio import *
   6  import e32, miso
   7  
   8  def change_duration():
   9      global duration
  10      answer = query(u'How long?', 'time', 18000.0)
  11      if answer:
  12          duration = int(answer/60)
  13          if duration <= 200:
  14              if query(u'Change to hr:min ?', 'query'):
  15                  duration *= 60
  16  
  17  im = Image.new((60,48))
  18  def showtime(rect=None):
  19      im.clear()
  20      im.text((5,28), u"%02d:%02d" % divmod(duration,60), font='title')
  21      c.blit(im, target=(0,0,180,144), scale=1)    # triple size
  22  
  23  duration = 300
  24  running = 0
  25  app.body = c = Canvas(showtime)
  26  alert = Sound.open(u'Z:\\Nokia\\Sounds\\Digital\\Cuckoo.awb')
  27  showtime()
  28  
  29  def start():
  30      global duration, running
  31      running = 1
  32      while running:
  33          duration -= 1
  34          showtime()
  35          if duration <= 0:
  36              alert.play(-2)  # repeat play
  37              break
  38          if duration % 10 == 0:
  39              miso.reset_inactivity_time()
  40          e32.ao_sleep(1)
  41  
  42  def toggle():
  43      global running
  44      if alert.state() == EPlaying:
  45          alert.stop()
  46          return
  47      running = 1 - running
  48      if running:
  49          start()
  50  
  51  def quit():
  52      global running
  53      running = 0
  54      if alert.state() == EPlaying:
  55          alert.stop()
  56      lock.signal()
  57  
  58  lock = e32.Ao_lock()
  59  c.bind(EKeySelect, toggle)  # start, pause, resume
  60  app.menu = [(u'Duration', change_duration),(u'Close', quit)]
  61  app.exit_key_handler = quit
  62  lock.wait()

Remind yourself of how fast time fly with this app.
You should change the sound file to the one you like.
(I use cuckoo.awb)
The duration input abues the time input by treating input
as minutes and seconds instead of hours and minutes.
But if the duration is too short, it will ask you if you mean
hours and minutes.
« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS