diff --git a/.document b/.document deleted file mode 100644 index 3d618dd..0000000 --- a/.document +++ /dev/null @@ -1,5 +0,0 @@ -lib/**/*.rb -bin/* -- -features/**/*.feature -LICENSE.txt diff --git a/.gitignore b/.gitignore index 01b37d0..64b7668 100644 --- a/.gitignore +++ b/.gitignore @@ -1,49 +1,18 @@ -# rcov generated coverage coverage.data - -# rdoc generated rdoc - -# yard generated doc .yardoc - -# bundler .bundle - -# jeweler generated +Gemfile.lock pkg - -# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: -# -# * Create a file at ~/.gitignore -# * Include files you want ignored -# * Run: git config --global core.excludesfile ~/.gitignore -# -# After doing this, these files will be ignored in all your git projects, -# saving you from having to 'pollute' every project you touch with them -# -# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line) -# -# For MacOS: -# .DS_Store - -# For TextMate *.tmproj tmtags - -# For emacs: *~ \#* .\#* - -# For vim: -*.swp - -# For redcar: +*.sw[p-n] .redcar - -# For rubinius: *.rbc +.document diff --git a/Gemfile b/Gemfile index f30cf21..3be9c3c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,15 +1,2 @@ -source "http://rubygems.org" - -gem 'ffi-libc' - -# Add dependencies to develop your gem here. -# Include everything needed to run rake, tests, features, etc. -group :development do - gem "shoulda" - gem "yard" - gem "redcarpet" - gem "rdoc" - gem "bundler" - gem "jeweler" - gem "simplecov" -end +source "https://rubygems.org" +gemspec diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 627102e..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,52 +0,0 @@ -GEM - remote: http://rubygems.org/ - specs: - activesupport (3.2.12) - i18n (~> 0.6) - multi_json (~> 1.0) - bourne (1.1.2) - mocha (= 0.10.5) - ffi (1.1.0) - ffi-libc (0.0.5) - ffi (>= 0.6.0, <= 1.1.0) - git (1.2.5) - i18n (0.6.4) - jeweler (1.8.4) - bundler (~> 1.0) - git (>= 1.2.5) - rake - rdoc - json (1.7.7) - metaclass (0.0.1) - mocha (0.10.5) - metaclass (~> 0.0.1) - multi_json (1.6.1) - rake (10.0.3) - rdoc (4.0.0) - json (~> 1.4) - redcarpet (2.2.2) - shoulda (3.3.2) - shoulda-context (~> 1.0.1) - shoulda-matchers (~> 1.4.1) - shoulda-context (1.0.2) - shoulda-matchers (1.4.2) - activesupport (>= 3.0.0) - bourne (~> 1.1.2) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) - yard (0.8.5.2) - -PLATFORMS - ruby - -DEPENDENCIES - bundler - ffi-libc - jeweler - rdoc - redcarpet - shoulda - simplecov - yard diff --git a/README.md b/README.md index 2ff58c5..3a79004 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ timeout-interrupt ================= -Works like ruby's timeout, but interrupts every call, also syscalls, which blocks the hole ruby-process. +Works like ruby's timeout, but interrupts *every call*, also syscalls, which blocks the hole ruby-process. It uses POSIX's alarm and traps ALRM-signals. -Known limitations bacause of alarm and ALRM are, that you can not use alarm or trap ALRM. +Known limitations bacause of alarm and ALRM are, that you can not use alarm or trap ALRM in the same time. + Scopes ====== @@ -23,27 +24,30 @@ If you want to know, which was raised, you need custom exceptions: class CustomErrorWillBeRaised e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" - exit e.status_code -end -require 'rake' - -require 'jeweler' -Jeweler::Tasks.new do |gem| - # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options - gem.name = "timeout-interrupt" - gem.homepage = "http://github.com/DenisKnauf/ruby-timeout-interrupt" - gem.license = "LGPLv3" - gem.summary = %Q{"Interrupts systemcalls too."} - gem.description = %Q{Timeout-lib, which interrupts everything, also systemcalls. It uses libc-alarm.} - gem.email = "Denis.Knauf@gmail.com" - gem.authors = ["Denis Knauf"] - # dependencies defined in Gemfile -end -Jeweler::RubygemsDotOrgTasks.new +require "bundler/gem_tasks" +task :default => :spec require 'rake/testtask' -Rake::TestTask.new(:test) do |test| +Rake::TestTask.new :test do |test| test.libs << 'lib' << 'test' test.pattern = 'test/**/test_*.rb' test.verbose = true end - -#require 'simplecov' -#Rcov::RcovTask.new do |test| - #test.libs << 'test' - #test.pattern = 'test/**/test_*.rb' - #test.verbose = true - #test.rcov_opts << '--exclude "gems/*"' -#end - -task :default => :test - -require 'yard' -YARD::Rake::YardocTask.new diff --git a/lib/timeout_interrupt.rb b/lib/timeout_interrupt.rb index 5c46ff8..4e59b24 100644 --- a/lib/timeout_interrupt.rb +++ b/lib/timeout_interrupt.rb @@ -1,23 +1,6 @@ require 'ffi/libc' require 'timeout' -# Provided by ffi-libc-lib and extended by this library, if needed. -# Older version of ffi-libc does not provide {FFI::LibC.alarm} -module FFI - module LibC - # @!method alarm(seconds) - # Sets an alarm. After `seconds` it will send an ALRM-signal to this process. - # - # Predefined alarm will be reset and will forget. - # @note Older implementations of ffi-libc does not provide {alarm}, but we need it. - # So we detect, if it is not provided and attach it. - # @param seconds [0] Clears alarm. - # @param seconds [Integer] How many seconds should be waited, before ALRM-signal should be send? - # @return (nil) - attach_function :alarm, [:uint], :uint unless FFI::LibC.respond_to? :alarm - end -end - # Helper module for `TimeoutInterrupt` # @see TimeoutInterrupt module TimeoutInterruptSingleton @@ -51,7 +34,7 @@ module TimeoutInterruptSingleton # @return [nil] def raise_if_sb_timed_out return if self.timeouts.empty? - key, (at, bt, exception) = self.timeouts.min_by {|key,(at,bt,ex)| at } + _key, (at, bt, exception) = self.timeouts.min_by {|_key,(at,_bt,_ex)| at } return if Time.now < at raise exception, 'execution expired', bt end @@ -66,7 +49,7 @@ module TimeoutInterruptSingleton else raise_if_sb_timed_out Signal.trap 'ALRM', &method( :alarm_trap) - key, (at, bt) = timeouts.min_by {|key,(at,bt)| at } + _key, (at, _bt) = timeouts.min_by {|_key,(at,_bt)| at } FFI::LibC.alarm (at - Time.now).to_i + 1 end nil @@ -76,9 +59,9 @@ module TimeoutInterruptSingleton # # @param seconds [0] No timeout, so block can take any time. # @param seconds [Integer] In `seconds` Seconds, it should raise a timeout, if not finished. - # @param seconds [nil] If also no block given, everything will be ignored and - # it will call {setup} for checking and preparing next known timeout. - # @param exception [Exception] which will be raised if timed out. + # @param seconds [nil] If this and no block given, it will call {setup} for checking and + # preparing _next_ known timeout. + # @param exception [exception] which exception will be raised if timed out? # @param exception [nil] `TimeoutInterrupt::Error` will be used to raise. # @param block [Proc] Will be called and should finish its work before it timed out. # @param block [nil] Nothing will happen, instead it will return a Proc, @@ -87,7 +70,8 @@ module TimeoutInterruptSingleton # Or if not, it will return a Proc, which will expect a Proc if called. # This Proc has no arguments and will prepare a timeout, like if you had given a block. # - # You can rescue `Timeout::Error`, instead `TimeoutInterrupt::Error`, it will work too. + # You can rescue `Timeout::Error`, instead `TimeoutInterrupt::Error`, + # it is a subclass of `Timeout::Error`. # # It will call your given block, which has `seconds` seconds to end. # If you want to prepare a timeout, which should be used many times, diff --git a/test/helper.rb b/test/helper.rb index ae51d27..ae0af92 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,5 +1,6 @@ require 'rubygems' require 'bundler' + begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e @@ -7,6 +8,7 @@ rescue Bundler::BundlerError => e $stderr.puts "Run `bundle install` to install missing gems" exit e.status_code end + require 'test/unit' require 'shoulda' @@ -14,9 +16,6 @@ require 'timeout' require 'benchmark' require 'ffi/libc' -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -$LOAD_PATH.unshift(File.dirname(__FILE__)) - require 'timeout_interrupt' class Test::Unit::TestCase diff --git a/test/test_ruby-timeout-interrupt.rb b/test/test_ruby-timeout-interrupt.rb index 7e87cfe..3567eae 100644 --- a/test/test_ruby-timeout-interrupt.rb +++ b/test/test_ruby-timeout-interrupt.rb @@ -4,7 +4,7 @@ class TestRubyTimeoutInterrupt < Test::Unit::TestCase def blocking t = FFI::LibC.fopen '/dev/ptmx', 'r' b = FFI::LibC.malloc 1025 - s = FFI::LibC.fread b, 1, 1024, t + FFI::LibC.fread b, 1, 1024, t ensure FFI::LibC.fclose t if t FFI::LibC.free b if b @@ -114,7 +114,7 @@ class TestRubyTimeoutInterrupt < Test::Unit::TestCase called = false prepared.call do assert_raise TimeoutInterrupt::Error, 'It should time out after one second, but it did not.' do - prepared.call { 2; sleep 2 } + prepared.call { _ = 2; sleep 2 } end called = true end diff --git a/timeout-interrupt.gemspec b/timeout-interrupt.gemspec index 904de4f..0fb6775 100644 --- a/timeout-interrupt.gemspec +++ b/timeout-interrupt.gemspec @@ -1,71 +1,33 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' -# -*- encoding: utf-8 -*- +Gem::Specification.new do |spec| + spec.name = "timeout-interrupt" + spec.version = "0.4.0" -Gem::Specification.new do |s| - s.name = "timeout-interrupt" - s.version = "0.3.0" + spec.authors = ["Denis Knauf"] + spec.description = "Timeout-lib, which interrupts everything, also systemcalls. It uses libc-alarm." + spec.email = ["git+timeout-interrupt@denkn.at"] - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Denis Knauf"] - s.date = "2013-03-14" - s.description = "Timeout-lib, which interrupts everything, also systemcalls. It uses libc-alarm." - s.email = "Denis.Knauf@gmail.com" - s.extra_rdoc_files = [ - "LICENSE.txt", - "README.md" - ] - s.files = [ - ".document", - "Gemfile", - "Gemfile.lock", - "LICENSE.txt", - "README.md", - "Rakefile", - "VERSION", - "lib/timeout_interrupt.rb", - "test/helper.rb", - "test/test_ruby-timeout-interrupt.rb", - "timeout-interrupt.gemspec" - ] - s.homepage = "http://github.com/DenisKnauf/ruby-timeout-interrupt" - s.licenses = ["LGPLv3"] - s.require_paths = ["lib"] - s.rubygems_version = "1.8.11" - s.summary = "\"Interrupts systemcalls too.\"" + spec.summary = "\"Interrupts systemcalls too.\"" + spec.licenses = ["LGPLv3"] - if s.respond_to? :specification_version then - s.specification_version = 3 + spec.homepage = "https://git.denkn.at/deac/ruby-timeout-interrupt" + spec.required_ruby_version = Gem::Requirement.new(">= 2.1.0") - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_runtime_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = spec.homepage + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do + `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + end + spec.bindir = "bin" + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] + + spec.add_runtime_dependency 'ffi-libc', '>= 0.1.1' + spec.add_development_dependency 'test-unit' + spec.add_development_dependency 'shoulda' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'bundler' end -