diff options
Diffstat (limited to 'lib/dtas/sigevent/fiddle_efd.rb')
-rw-r--r-- | lib/dtas/sigevent/fiddle_efd.rb | 38 |
1 files changed, 38 insertions, 0 deletions
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 <dtas-all@nongnu.org> +# 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 |