From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.9 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 19F1D1F463 for ; Fri, 20 Dec 2019 01:39:39 +0000 (UTC) Received: from localhost ([::1]:49624 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ii7GU-0002kh-AS for e@80x24.org; Thu, 19 Dec 2019 20:39:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36441) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ii7GQ-0002kC-S4 for dtas-all@nongnu.org; Thu, 19 Dec 2019 20:39:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ii7GP-0001ey-3t for dtas-all@nongnu.org; Thu, 19 Dec 2019 20:39:34 -0500 Received: from dcvr.yhbt.net ([64.71.152.64]:49650) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ii7GO-0001au-OV for dtas-all@nongnu.org; Thu, 19 Dec 2019 20:39:32 -0500 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 9E2481F46C for ; Fri, 20 Dec 2019 01:39:18 +0000 (UTC) From: Eric Wong To: dtas-all@nongnu.org Subject: [PATCH v2 2/5] provide fiddle-based eventfd implementation Date: Fri, 20 Dec 2019 01:39:14 +0000 Message-Id: <20191220013917.17212-3-e@80x24.org> In-Reply-To: <20191220013917.17212-1-e@80x24.org> References: <20191220013917.17212-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 64.71.152.64 X-BeenThere: dtas-all@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: duct tape audio suite List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dtas-all-bounces+e=80x24.org@nongnu.org Sender: "dtas-all" 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 ||=3D File.open('/dev/null', 'r+') end =20 + @libc =3D nil + def self.libc + @libc ||=3D begin + require 'fiddle' + Fiddle.dlopen(nil) + end + end + # String#-@ will deduplicate strings when Ruby 2.5 is released (Dec 20= 17) # https://bugs.ruby-lang.org/issues/13077 if RUBY_VERSION.to_f >=3D 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 @@ =20 # 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_e= fd.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 +# License: GPL-3.0+ +# 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 =3D Fiddle::Function.new(DTAS.libc['eventfd'], + [ Fiddle::TYPE_INT, Fiddle::TYPE_INT ], # initval, flags + Fiddle::TYPE_INT) # fd + + attr_reader :to_io + ONE =3D [ 1 ].pack('Q').freeze + + def initialize + fd =3D EventFD.call(0, 02000000|00004000) # EFD_CLOEXEC|EFD_NONBLOCK + raise "eventfd failed: #{Fiddle.last_error}" if fd < 0 + @to_io =3D DTAS::Nonblock.for_fd(fd) + @buf =3D ''.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 =20 # 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 +# License: GPL-3.0+ +# frozen_string_literal: true +require_relative 'helper' +require 'dtas' +require 'dtas/sigevent' + +class TestSigevent < Testcase + def test_sigevent + io =3D DTAS::Sigevent.new + io.signal + assert IO.select([io]), 'IO.select returns' + res =3D 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