pax_global_header00006660000000000000000000000064140742444730014523gustar00rootroot0000000000000052 comment=fb3dc859f3580e845193ddd95daaf69618cfdd63 ruby-async-process-1.3.1/000077500000000000000000000000001407424447300152755ustar00rootroot00000000000000ruby-async-process-1.3.1/.editorconfig000066400000000000000000000000641407424447300177520ustar00rootroot00000000000000root = true [*] indent_style = tab indent_size = 2 ruby-async-process-1.3.1/.github/000077500000000000000000000000001407424447300166355ustar00rootroot00000000000000ruby-async-process-1.3.1/.github/workflows/000077500000000000000000000000001407424447300206725ustar00rootroot00000000000000ruby-async-process-1.3.1/.github/workflows/async-head.yml000066400000000000000000000007531407424447300234360ustar00rootroot00000000000000name: Async head on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - head env: BUNDLE_GEMFILE: gems/async-head.rb steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: bundle exec rspec ruby-async-process-1.3.1/.github/workflows/async-v1.yml000066400000000000000000000007461407424447300230650ustar00rootroot00000000000000name: Async v1 on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - 2.7 env: BUNDLE_GEMFILE: gems/async-v1.rb steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: bundle exec rspec ruby-async-process-1.3.1/.github/workflows/development.yml000066400000000000000000000015741407424447300237460ustar00rootroot00000000000000name: Development on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - 2.5 - 2.6 - 2.7 - 3.0 experimental: [false] env: [""] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@master with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: ${{matrix.env}} bundle exec rspec ruby-async-process-1.3.1/.gitignore000066400000000000000000000001761407424447300172710ustar00rootroot00000000000000/.bundle/ /.yardoc /gems.locked /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ # rspec failure tracking .rspec_status ruby-async-process-1.3.1/.rspec000066400000000000000000000000671407424447300164150ustar00rootroot00000000000000--format documentation --warnings --require spec_helperruby-async-process-1.3.1/README.md000066400000000000000000000044371407424447300165640ustar00rootroot00000000000000# Async::Process Implements `Process.spawn` and `Process.capture` for [async](https://github.com/socketry/async). [![Development Status](https://github.com/socketry/async-process/workflows/Development/badge.svg)](https://github.com/socketry/async-process/actions?workflow=Development) ## Installation Add this line to your application's Gemfile: ``` ruby gem 'async-process' ``` And then execute: $ bundle Or install it yourself as: $ gem install async-process ## Usage In any asynchronous context (e.g. a reactor), simply use the `Async::Process.spawn` rather than `Process.spawn` like so: ``` ruby require 'async/process' Async::Reactor.run do status = Async::Process.spawn("ls", "-lah") end ``` Internally, we use a thread, since `nio4r` doesn't support monitoring pids. ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request ## See Also - [async-container](https://github.com/socketry/async-container) — Execute multiple isolated threads and/or processes. ## License Released under the MIT license. Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby-async-process-1.3.1/async-process.gemspec000066400000000000000000000012221407424447300214300ustar00rootroot00000000000000 require_relative "lib/async/process/version" Gem::Specification.new do |spec| spec.name = "async-process" spec.version = Async::Process::VERSION spec.summary = "Asynchronous process spawning." spec.authors = ["Samuel Williams"] spec.license = "MIT" spec.homepage = "https://github.com/socketry/async-process" spec.files = Dir.glob('{lib}/**/*', File::FNM_DOTMATCH, base: __dir__) spec.add_dependency "async" spec.add_dependency "async-io" spec.add_development_dependency "async-rspec", "~> 1.1" spec.add_development_dependency "bundler" spec.add_development_dependency "covered" spec.add_development_dependency "rspec", "~> 3.0" end ruby-async-process-1.3.1/gems.rb000066400000000000000000000002331407424447300165530ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec group :maintenance, optional: true do gem "bake-modernize" gem "bake-bundler" end ruby-async-process-1.3.1/gems/000077500000000000000000000000001407424447300162305ustar00rootroot00000000000000ruby-async-process-1.3.1/gems/async-head.rb000066400000000000000000000002111407424447300205630ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec path: "../" gem 'async', git: "https://github.com/socketry/async" ruby-async-process-1.3.1/gems/async-v1.rb000066400000000000000000000001511407424447300202130ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec path: "../" gem 'async', '~> 1.0' ruby-async-process-1.3.1/lib/000077500000000000000000000000001407424447300160435ustar00rootroot00000000000000ruby-async-process-1.3.1/lib/async/000077500000000000000000000000001407424447300171605ustar00rootroot00000000000000ruby-async-process-1.3.1/lib/async/process.rb000066400000000000000000000031601407424447300211630ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'async/process/version' require 'async/process/child' require 'async/io' require 'kernel/sync' module Async module Process def self.spawn(*arguments, **options) Child.new(*arguments, **options).wait end def self.capture(*arguments, **options) input, output = Async::IO.pipe options[:out] = output.io runner = Async do spawn(*arguments, **options) ensure output.close end Sync do input.read ensure runner.wait input.close end end end end ruby-async-process-1.3.1/lib/async/process/000077500000000000000000000000001407424447300206365ustar00rootroot00000000000000ruby-async-process-1.3.1/lib/async/process/child.rb000066400000000000000000000042161407424447300222510ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'async/io/generic' module Async module Process class Child def initialize(*args, **options) # Setup a cross-thread notification pipe - nio4r can't monitor pids unfortunately: pipe = ::IO.pipe @input = Async::IO::Generic.new(pipe.first) @output = pipe.last @exit_status = nil @pid = ::Process.spawn(*args, **options, pgroup: true) @thread = Thread.new do _, @exit_status = ::Process.wait2(@pid) @output.close end end attr :pid def running? @exit_status.nil? end def kill(signal = :TERM) ::Process.kill(signal, -@pid) end def wait if @exit_status.nil? wait_thread end return @exit_status end private def wait_thread @input.read(1) ensure # If the user stops this task, we kill the process: if @exit_status.nil? ::Process.kill(:KILL, -@pid) end @thread.join # We are done with the notification pipe: @input.close @output.close end end end end ruby-async-process-1.3.1/lib/async/process/version.rb000066400000000000000000000022471407424447300226550ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. module Async module Process VERSION = "1.3.1" end end ruby-async-process-1.3.1/spec/000077500000000000000000000000001407424447300162275ustar00rootroot00000000000000ruby-async-process-1.3.1/spec/async/000077500000000000000000000000001407424447300173445ustar00rootroot00000000000000ruby-async-process-1.3.1/spec/async/process/000077500000000000000000000000001407424447300210225ustar00rootroot00000000000000ruby-async-process-1.3.1/spec/async/process/child_spec.rb000066400000000000000000000027461407424447300234550ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'async/process' RSpec.describe Async::Process::Child do include_context Async::RSpec::Reactor it "will terminate sub-process when stopping task" do child = nil task = reactor.async do child = described_class.new("sleep 60") child.wait end expect(child).to be_running task.stop task.wait expect(child).to_not be_running end end ruby-async-process-1.3.1/spec/async/process_spec.rb000066400000000000000000000027221407424447300223640ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'async/process' RSpec.describe Async::Process do include_context Async::RSpec::Reactor it "should execute sub-process" do status = described_class.spawn("ls", "-lah") expect(status).to be_success end it "can capture output" do output = described_class.capture("ls", "-lah") expect(output).to include("async-process") end end ruby-async-process-1.3.1/spec/spec_helper.rb000066400000000000000000000004651407424447300210520ustar00rootroot00000000000000 require "bundler/setup" require "covered/rspec" # Shared rspec helpers: require "async/rspec" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" config.expect_with :rspec do |c| c.syntax = :expect end end