[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 2/5] provide fiddle-based eventfd implementation
From: |
Eric Wong |
Subject: |
[PATCH v2 2/5] provide fiddle-based eventfd implementation |
Date: |
Fri, 20 Dec 2019 01:39:14 +0000 |
sleepy_penguin requires a compiler and development headers to
install, so it could be a PITA to install for users on
distro-provided Ruby. Allow fiddle since it's part of the Ruby
standard library since 1.9.2 and users won't have to install
anything else.
---
lib/dtas.rb | 8 +++++++
lib/dtas/sigevent.rb | 7 ++++--
lib/dtas/sigevent/efd.rb | 2 ++
lib/dtas/sigevent/fiddle_efd.rb | 38 +++++++++++++++++++++++++++++++++
lib/dtas/sigevent/pipe.rb | 2 +-
test/test_sigevent.rb | 20 +++++++++++++++++
6 files changed, 74 insertions(+), 3 deletions(-)
create mode 100644 lib/dtas/sigevent/fiddle_efd.rb
create mode 100644 test/test_sigevent.rb
diff --git a/lib/dtas.rb b/lib/dtas.rb
index 7e9c0d5..ae2f815 100644
--- a/lib/dtas.rb
+++ b/lib/dtas.rb
@@ -25,6 +25,14 @@ def self.null # :nodoc:
@null ||= File.open('/dev/null', 'r+')
end
+ @libc = nil
+ def self.libc
+ @libc ||= begin
+ require 'fiddle'
+ Fiddle.dlopen(nil)
+ end
+ end
+
# String#-@ will deduplicate strings when Ruby 2.5 is released (Dec 2017)
# https://bugs.ruby-lang.org/issues/13077
if RUBY_VERSION.to_f >= 2.5
diff --git a/lib/dtas/sigevent.rb b/lib/dtas/sigevent.rb
index d4a96d7..74d22df 100644
--- a/lib/dtas/sigevent.rb
+++ b/lib/dtas/sigevent.rb
@@ -3,8 +3,11 @@
# frozen_string_literal: true
begin
raise LoadError, "no eventfd with _DTAS_POSIX" if ENV["_DTAS_POSIX"]
- require 'sleepy_penguin'
- require_relative 'sigevent/efd'
+ begin
+ require_relative 'sigevent/efd'
+ rescue LoadError
+ require_relative 'sigevent/fiddle_efd'
+ end
rescue LoadError
require_relative 'sigevent/pipe'
end
diff --git a/lib/dtas/sigevent/efd.rb b/lib/dtas/sigevent/efd.rb
index 4be2c84..22772ee 100644
--- a/lib/dtas/sigevent/efd.rb
+++ b/lib/dtas/sigevent/efd.rb
@@ -3,6 +3,8 @@
# used in various places for safe wakeups from IO.select via signals
# This requires a modern Linux system and the "sleepy_penguin" RubyGem
+require 'sleepy_penguin'
+
class DTAS::Sigevent < SleepyPenguin::EventFD # :nodoc:
def self.new
super(0, :CLOEXEC)
diff --git a/lib/dtas/sigevent/fiddle_efd.rb b/lib/dtas/sigevent/fiddle_efd.rb
new file mode 100644
index 0000000..e29f6ca
--- /dev/null
+++ b/lib/dtas/sigevent/fiddle_efd.rb
@@ -0,0 +1,38 @@
+# Copyright (C) 2013-2019 all contributors <address@hidden>
+# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
+# frozen_string_literal: true
+
+# used in various places for safe wakeups from IO.select via signals
+# This requires a modern GNU/Linux system with eventfd(2) support
+require_relative '../nonblock'
+require 'fiddle'
+class DTAS::Sigevent # :nodoc:
+
+ EventFD = Fiddle::Function.new(DTAS.libc['eventfd'],
+ [ Fiddle::TYPE_INT, Fiddle::TYPE_INT ], # initval, flags
+ Fiddle::TYPE_INT) # fd
+
+ attr_reader :to_io
+ ONE = [ 1 ].pack('Q').freeze
+
+ def initialize
+ fd = EventFD.call(0, 02000000|00004000) # EFD_CLOEXEC|EFD_NONBLOCK
+ raise "eventfd failed: #{Fiddle.last_error}" if fd < 0
+ @to_io = DTAS::Nonblock.for_fd(fd)
+ @buf = ''.b
+ end
+
+ def signal
+ @to_io.syswrite(ONE)
+ end
+
+ def readable_iter
+ @to_io.read_nonblock(8, @buf, exception: false)
+ yield self, nil # calls DTAS::Process.reaper
+ :wait_readable
+ end
+
+ def close
+ @to_io.close
+ end
+end
diff --git a/lib/dtas/sigevent/pipe.rb b/lib/dtas/sigevent/pipe.rb
index 921a5b3..0ea9d31 100644
--- a/lib/dtas/sigevent/pipe.rb
+++ b/lib/dtas/sigevent/pipe.rb
@@ -3,7 +3,7 @@
# frozen_string_literal: true
# used in various places for safe wakeups from IO.select via signals
-# A fallback for non-Linux systems lacking the "sleepy_penguin" RubyGem
+# A fallback for non-Linux systems lacking the "splice" syscall
require_relative '../nonblock'
class DTAS::Sigevent # :nodoc:
attr_reader :to_io
diff --git a/test/test_sigevent.rb b/test/test_sigevent.rb
new file mode 100644
index 0000000..6cfe528
--- /dev/null
+++ b/test/test_sigevent.rb
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 all contributors <address@hidden>
+# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
+# frozen_string_literal: true
+require_relative 'helper'
+require 'dtas'
+require 'dtas/sigevent'
+
+class TestSigevent < Testcase
+ def test_sigevent
+ io = DTAS::Sigevent.new
+ io.signal
+ assert IO.select([io]), 'IO.select returns'
+ res = io.readable_iter do |f,arg|
+ assert_same io, f
+ assert_nil arg
+ end
+ assert_equal :wait_readable, res
+ assert_nil io.close
+ end
+end