process-group 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3f61fd5af23be851198506a9872307595aef290fe9264c0edd62b8036f143b2
4
- data.tar.gz: a4f52c431b3b123bf4ca0cdaacb778706b35099a5be7deb17359ff260bd927f0
3
+ metadata.gz: 38e06a3ab81ffc75c98a332e2e92b105bd2e92facd4cffcd8bb51c6c7c3c8726
4
+ data.tar.gz: 79af5a9a36c886e74258d83c4641f7acdbcf26ded2fd3db88bf1872f88324882
5
5
  SHA512:
6
- metadata.gz: 04c5f7734d1e0894d7b5c0c477cf67999629ba159a910a96c17f3e951e84b278faa9b0a2274af650fc4b3e430c76de9326f1e5267643bdefec4d593c0a1e7cac
7
- data.tar.gz: 6f35d68540b6fbb413db465a7befb284713d85bb9105cd9924eb48b8b540be91ca0d312f9398fe4ecc8e86c8708ce6da08bd1b715021230aa0a994a9aff98282
6
+ metadata.gz: e5eb50575f97b84b9c3bf171484bf82e02b2e97e7546bf49f9ed0ec8b7dea15751137c4baf40af95890ffff0506ada4f1533400ec747854a41a3275b3c81a126
7
+ data.tar.gz: 7679dd3394e8da2e9eb4f1f35bc41e9110e2bef472b8e4afd68d85b4ee0676b96c11ab481feb4413720ace5ea002c063233b8fb42a42b029bd336626057366d1
@@ -50,6 +50,10 @@ module Process
50
50
  def resume(*arguments)
51
51
  @fiber.resume(*arguments)
52
52
  end
53
+
54
+ def kill(signal = :INT)
55
+ Process.kill(signal, @pid)
56
+ end
53
57
  end
54
58
 
55
59
  # Executes a command using Process.spawn with the given arguments and options.
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Process
22
22
  class Group
23
- VERSION = "1.2.1"
23
+ VERSION = "1.2.2"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process-group
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-12 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: process-terminal
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.2.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: covered
28
+ name: bake-bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: bake-modernize
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,21 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 3.4.0
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 3.4.0
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: covered
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -80,39 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- description: "\tManages a unix process group for running multiple processes, keeps
84
- track of multiple processes and leverages fibers to provide predictable behaviour
85
- in complicated process-based scripts.\n"
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.9.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.9.0
97
+ description:
86
98
  email:
87
- - samuel.williams@oriontransfer.co.nz
88
99
  executables: []
89
100
  extensions: []
90
101
  extra_rdoc_files: []
91
102
  files:
92
- - ".gitignore"
93
- - ".rspec"
94
- - ".travis.yml"
95
- - Gemfile
96
- - README.md
97
- - Rakefile
98
- - examples/terminal.rb
99
103
  - lib/process/group.rb
100
104
  - lib/process/group/version.rb
101
- - process-group.gemspec
102
- - spec/process/group/foreground_spec.rb
103
- - spec/process/group/fork_spec.rb
104
- - spec/process/group/interrupt_spec.rb
105
- - spec/process/group/io_spec.rb
106
- - spec/process/group/load_spec.rb
107
- - spec/process/group/process_spec.rb
108
- - spec/process/group/spawn_spec.rb
109
- - spec/process/group/wait_spec.rb
110
- - spec/spec_helper.rb
111
105
  homepage: https://github.com/ioquatix/process-group
112
106
  licenses:
113
107
  - MIT
114
- metadata: {}
115
- post_install_message:
108
+ metadata:
109
+ funding_uri: https://github.com/sponsors/ioquatix/
110
+ post_install_message:
116
111
  rdoc_options: []
117
112
  require_paths:
118
113
  - lib
@@ -127,17 +122,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
122
  - !ruby/object:Gem::Version
128
123
  version: '0'
129
124
  requirements: []
130
- rubygems_version: 3.0.6
131
- signing_key:
125
+ rubygems_version: 3.1.2
126
+ signing_key:
132
127
  specification_version: 4
133
- summary: Run processes concurrently in separate fibers with predictable behaviour.
134
- test_files:
135
- - spec/process/group/foreground_spec.rb
136
- - spec/process/group/fork_spec.rb
137
- - spec/process/group/interrupt_spec.rb
138
- - spec/process/group/io_spec.rb
139
- - spec/process/group/load_spec.rb
140
- - spec/process/group/process_spec.rb
141
- - spec/process/group/spawn_spec.rb
142
- - spec/process/group/wait_spec.rb
143
- - spec/spec_helper.rb
128
+ summary: Run and manage multiple processes in separate fibers with predictable behaviour.
129
+ test_files: []
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- # rspec failure tracking
12
- .rspec_status
data/.rspec DELETED
@@ -1,4 +0,0 @@
1
- --format documentation
2
- --backtrace
3
- --warnings
4
- --require spec_helper
@@ -1,14 +0,0 @@
1
- language: ruby
2
- dist: xenial
3
- cache: bundler
4
-
5
- matrix:
6
- include:
7
- - rvm: 2.3
8
- - rvm: 2.4
9
- - rvm: 2.5
10
- - rvm: 2.6
11
- - rvm: 2.6
12
- os: osx
13
- - rvm: 2.6
14
- env: COVERAGE=BriefSummary,Coveralls
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in process-pool.gemspec
4
- gemspec
5
-
6
- group :test do
7
- gem 'irb'
8
- end
data/README.md DELETED
@@ -1,219 +0,0 @@
1
- # Process::Group
2
-
3
- `Process::Group` allows for multiple fibers to run system processes concurrently with minimal overhead.
4
-
5
- ```ruby
6
- Process::Group.wait do |group|
7
- group.run("ls", "-lah") {|status| puts status.inspect}
8
- group.run("echo", "Hello World") {|status| puts status.inspect}
9
- end
10
- ```
11
-
12
- [![Build Status](https://secure.travis-ci.com/socketry/process-group.svg)](http://travis-ci.com/socketry/process-group)
13
- [![Coverage Status](https://coveralls.io/repos/socketry/process-group/badge.svg)](https://coveralls.io/r/socketry/process-group)
14
- [![Documentation](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/gems/process-group)
15
- [![Code](http://img.shields.io/badge/github-code-blue.svg)](https://github.com/socketry/process-group)
16
-
17
- ## Installation
18
-
19
- Add this line to your application's Gemfile:
20
-
21
- gem 'process-group'
22
-
23
- And then execute:
24
-
25
- $ bundle
26
-
27
- Or install it yourself as:
28
-
29
- $ gem install process-group
30
-
31
- ## Usage
32
-
33
- The simplest concurrent usage is as follows:
34
-
35
- # Create a new process group:
36
- Process::Group.wait do |group|
37
- # Run the command (non-blocking):
38
- group.run("sleep 1") do |exit_status|
39
- # Running in a separate fiber, will execute this code once the process completes:
40
- puts "Command finished with status: #{exit_status}"
41
- end
42
-
43
- # Do something else here:
44
- sleep(1)
45
-
46
- # Wait for all processes in group to finish.
47
- end
48
-
49
- The `group.wait` call is an explicit synchronization point, and if it completes successfully, all processes/fibers have finished successfully. If an error is raised in a fiber, it will be passed back out through `group.wait` and this is the only failure condition. Even if this occurs, all children processes are guaranteed to be cleaned up.
50
-
51
- ### Explicit Fibers
52
-
53
- Items within a single fiber will execute sequentially. Processes (e.g. via `Group#spawn`) will run concurrently in multiple fibers.
54
-
55
- ```ruby
56
- Process::Group.wait do |group|
57
- # Explicity manage concurrency in this fiber:
58
- Fiber.new do
59
- # These processes will be run sequentially:
60
- group.spawn("sleep 1")
61
- group.spawn("sleep 1")
62
- end.resume
63
-
64
- # Implicitly run this task concurrently as the above fiber:
65
- group.run("sleep 2")
66
- end
67
- ```
68
-
69
- `Group#spawn` is theoretically identical to `Process#spawn` except the processes are run concurrently if possible.
70
-
71
- ### Explicit Wait
72
-
73
- The recommended approach to use process group is to call `Process::Group.wait` with a block which invokes tasks. This block is wrapped in appropriate `rescue Interrupt` and `ensure` blocks which guarantee that the process group is cleaned up:
74
-
75
- ```ruby
76
- Process::Group.wait do |group|
77
- group.run("sleep 10")
78
- end
79
- ```
80
-
81
- It is also possible to invoke this machinery and reuse the process group simply by instantiating the group and calling wait explicitly:
82
-
83
- ```ruby
84
- group = Process::Group.new
85
-
86
- group.wait do
87
- group.run("sleep 10")
88
- end
89
- ```
90
-
91
- It is also possible to queue tasks for execution outside the wait block. But by design, it's only possible to execute tasks within the wait block. Tasks added outside a wait block will be queued up for execution when `#wait` is invoked:
92
-
93
- ```ruby
94
- group = Process::Group.new
95
-
96
- group.run("sleep 10")
97
-
98
- # Run command here:
99
- group.wait
100
- ```
101
-
102
- ### Specify Options
103
-
104
- You can specify options to `Group#run` and `Group#spawn` just like `Process::spawn`:
105
-
106
- ```ruby
107
- Process::Group.wait do |group|
108
- env = {'FOO' => 'BAR'}
109
-
110
- # Arguments are essentially the same as Process::spawn.
111
- group.run(env, "sleep 1", chdir: "/tmp")
112
- end
113
- ```
114
-
115
- ### Process Limit
116
-
117
- The process group can be used as a way to spawn multiple processes, but sometimes you'd like to limit the number of parallel processes to something relating to the number of processors in the system. By default, there is no limit on the number of processes running concurrently.
118
-
119
- ```ruby
120
- # limit based on the number of processors:
121
- require 'etc'
122
- group = Process::Group.new(limit: Etc.nprocessors)
123
-
124
- # hardcoded - set to n (8 < n < 32) and let the OS scheduler worry about it:
125
- group = Process::Group.new(limit: 32)
126
-
127
- # unlimited - default:
128
- group = Process::Group.new
129
- ```
130
-
131
- ### Kill Group
132
-
133
- It is possible to send a signal (kill) to the entire process group:
134
-
135
- ```ruby
136
- group.kill(:TERM)
137
- ```
138
-
139
- If there are no running processes, this is a no-op (rather than an error). [Proper handling of SIGINT/SIGQUIT](http://www.cons.org/cracauer/sigint.html) explains how to use signals correctly.
140
-
141
- #### Handling Interrupts
142
-
143
- `Process::Group` transparently handles `Interrupt` when raised within a `Fiber`. If `Interrupt` is raised, all children processes will be sent `kill(:INT)` and we will wait for all children to complete, but without resuming the controlling fibers. If `Interrupt` is raised during this process, children will be sent `kill(:TERM)`. After calling `Interrupt`, the fibers will not be resumed.
144
-
145
- ### Process Timeout
146
-
147
- You can run a process group with a time limit by using a separate child process:
148
-
149
- ```ruby
150
- group = Process::Group.new
151
-
152
- class Timeout < StandardError
153
- end
154
-
155
- Fiber.new do
156
- # Wait for 2 seconds, let other processes run:
157
- group.fork { sleep 2 }
158
-
159
- # If no other processes are running, we are done:
160
- Fiber.yield unless group.running?
161
-
162
- # Send SIGINT to currently running processes:
163
- group.kill(:INT)
164
-
165
- # Wait for 2 seconds, let other processes run:
166
- group.fork { sleep 2 }
167
-
168
- # If no other processes are running, we are done:
169
- Fiber.yield unless group.running?
170
-
171
- # Send SIGTERM to currently running processes:
172
- group.kill(:TERM)
173
-
174
- # Raise an Timeout exception which is based back out:
175
- raise Timeout
176
- end.resume
177
-
178
- # Run some other long task:
179
- group.run("sleep 10")
180
-
181
- # Wait for fiber to complete:
182
- begin
183
- group.wait
184
- rescue Timeout
185
- puts "Process group was terminated forcefully."
186
- end
187
- ```
188
-
189
- ## Contributing
190
-
191
- 1. Fork it
192
- 2. Create your feature branch (`git checkout -b my-new-feature`)
193
- 3. Commit your changes (`git commit -am 'Add some feature'`)
194
- 4. Push to the branch (`git push origin my-new-feature`)
195
- 5. Create new Pull Request
196
-
197
- ## License
198
-
199
- Released under the MIT license.
200
-
201
- Copyright, 2014, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
202
-
203
- Permission is hereby granted, free of charge, to any person obtaining a copy
204
- of this software and associated documentation files (the "Software"), to deal
205
- in the Software without restriction, including without limitation the rights
206
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
207
- copies of the Software, and to permit persons to whom the Software is
208
- furnished to do so, subject to the following conditions:
209
-
210
- The above copyright notice and this permission notice shall be included in
211
- all copies or substantial portions of the Software.
212
-
213
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
214
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
215
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
216
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
217
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
219
- THE SOFTWARE.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:test)
5
-
6
- task :default => :test
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require_relative '../lib/process/group'
24
-
25
- group = Process::Group.new
26
-
27
- 5.times do
28
- Fiber.new do
29
- result = group.fork do
30
- begin
31
- sleep 1 while true
32
- rescue Interrupt
33
- puts "Interrupted in child #{Process.pid}"
34
- end
35
- end
36
- end.resume
37
- end
38
-
39
- begin
40
- group.wait
41
- rescue Interrupt
42
- puts "Interrupted in parent #{Process.pid}"
43
- end
@@ -1,29 +0,0 @@
1
-
2
- require_relative 'lib/process/group/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "process-group"
6
- spec.version = Process::Group::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
- spec.description = <<-EOF
10
- Manages a unix process group for running multiple processes, keeps track of multiple processes and leverages fibers to provide predictable behaviour in complicated process-based scripts.
11
- EOF
12
- spec.summary = %q{Run processes concurrently in separate fibers with predictable behaviour.}
13
- spec.homepage = "https://github.com/ioquatix/process-group"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.required_ruby_version = '>= 2.0'
22
-
23
- spec.add_dependency "process-terminal", "~> 0.2.0"
24
-
25
- spec.add_development_dependency "covered"
26
- spec.add_development_dependency "bundler"
27
- spec.add_development_dependency "rspec", "~> 3.4.0"
28
- spec.add_development_dependency "rake"
29
- end
@@ -1,34 +0,0 @@
1
- # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "can run a process in the foreground" do
25
- output, input = IO.pipe
26
-
27
- subject.wait do
28
- subject.run("irb", foreground: true, in: output)
29
-
30
- input.puts("exit")
31
- input.close
32
- end
33
- end
34
- end
@@ -1,60 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "should fork and write to pipe" do
25
- input, output = IO.pipe
26
-
27
- Fiber.new do
28
- result = subject.fork do
29
- output.puts "Hello World"
30
-
31
- exit(1)
32
- end
33
-
34
- # We need to close output so that input.read will encounter end of stream.
35
- output.close
36
-
37
- expect(result.exitstatus).to be == 1
38
- end.resume
39
-
40
- subject.wait
41
-
42
- expect(input.read).to be == "Hello World\n"
43
- end
44
-
45
- it "should not throw interrupt from fork" do
46
- Fiber.new do
47
- result = subject.fork do
48
- # Don't print out a backtrace when Ruby invariably exits due to the execption below:
49
- $stderr.reopen('/dev/null', 'w')
50
-
51
- raise Interrupt
52
- end
53
-
54
- expect(result.exitstatus).not_to be == 0
55
- end.resume
56
-
57
- # Shouldn't raise any errors:
58
- subject.wait
59
- end
60
- end
@@ -1,146 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "should raise interrupt exception" do
25
- checkpoint = ""
26
-
27
- Fiber.new do
28
- checkpoint += 'X'
29
-
30
- result = subject.fork { sleep 0.1 }
31
-
32
- expect(result).to be == 0
33
-
34
- checkpoint += 'Y'
35
-
36
- # Simulate the user pressing Ctrl-C after a short time:
37
- raise Interrupt
38
- end.resume
39
-
40
- Fiber.new do
41
- checkpoint += 'A'
42
-
43
- # This never returns:
44
- result = subject.fork do
45
- # We do this to exit immediately.. otherwise Ruby will print a backtrace and that's a bit confusing.
46
- trap(:INT) { exit!(0) }
47
- sleep(0.2)
48
- end
49
-
50
- checkpoint += 'B'
51
- end.resume
52
-
53
- expect(subject).to receive(:kill).with(:INT).once.and_call_original
54
- expect(subject).to receive(:kill).with(:TERM).once.and_call_original
55
-
56
- expect do
57
- subject.wait
58
- end.to raise_error(Interrupt)
59
-
60
- expect(checkpoint).to be == 'XAY'
61
- end
62
-
63
- it "should raise an exception" do
64
- checkpoint = ""
65
-
66
- Fiber.new do
67
- checkpoint += 'X'
68
-
69
- result = subject.fork { sleep 0.1 }
70
- expect(result).to be == 0
71
-
72
- checkpoint += 'Y'
73
-
74
- # Raises a RuntimeError
75
- fail "Error"
76
- end.resume
77
-
78
- Fiber.new do
79
- checkpoint += 'A'
80
-
81
- # This never returns:
82
- result = subject.fork { sleep 0.2 }
83
-
84
- checkpoint += 'B'
85
- end.resume
86
-
87
- expect do
88
- expect(subject).to receive(:kill).with(:TERM).once
89
-
90
- subject.wait
91
- end.to raise_error(RuntimeError)
92
-
93
- expect(checkpoint).to be == 'XAY'
94
- end
95
-
96
- it "should pass back out exceptions" do
97
- checkpoint = ""
98
-
99
- Fiber.new do
100
- # Wait for 2 seconds, let other processes run:
101
- subject.fork { sleep 2 }
102
- checkpoint += 'A'
103
- #puts "Finished waiting #1..."
104
-
105
- # If no other processes are running, we are done:
106
- Fiber.yield unless subject.running?
107
- checkpoint += 'B'
108
- #puts "Sending SIGINT..."
109
-
110
- # Send SIGINT to currently running processes:
111
- subject.kill(:INT)
112
-
113
- # Wait for 2 seconds, let other processes run:
114
- subject.fork { sleep 2 }
115
- checkpoint += 'C'
116
- #puts "Finished waiting #2..."
117
-
118
- # If no other processes are running, we are done:
119
- Fiber.yield unless subject.running?
120
- checkpoint += 'D'
121
- #puts "Sending SIGTERM..."
122
-
123
- # Send SIGTERM to currently running processes:
124
- subject.kill(:TERM)
125
-
126
- # Raise an Timeout exception which is pased back out:
127
- raise StandardError.new("Should never get here!")
128
- end.resume
129
-
130
- # Run some other long task:
131
- subject.run("sleep 10")
132
-
133
- start_time = Time.now
134
-
135
- # Wait for fiber to complete:
136
- expect do
137
- subject.wait
138
- checkpoint += 'E'
139
- end.not_to raise_error
140
-
141
- end_time = Time.now
142
-
143
- expect(checkpoint).to be == 'ABCE'
144
- expect(end_time - start_time).to be_within(0.2).of 4.0
145
- end
146
- end
@@ -1,52 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "should read line on separate thread" do
25
- input, output = IO.pipe
26
-
27
- Fiber.new do
28
- result = subject.fork do
29
- 3.times do
30
- output.puts "Hello World"
31
- sleep 0.1
32
- end
33
-
34
- exit(0)
35
- end
36
-
37
- output.close
38
-
39
- expect(result).to be == 0
40
- end.resume
41
-
42
- lines = nil
43
- io_thread = Thread.new do
44
- lines = input.read
45
- end
46
-
47
- subject.wait
48
-
49
- io_thread.join
50
- expect(lines).to be == ("Hello World\n" * 3)
51
- end
52
- end
@@ -1,42 +0,0 @@
1
- # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group.new(limit: 5) do
24
- it "should only run a limited number of processes" do
25
- expect(subject.available?).to be_truthy
26
- expect(subject.blocking?).to be_falsey
27
-
28
- 5.times do
29
- Fiber.new do
30
- result = subject.fork do
31
- exit(0)
32
- end
33
-
34
- expect(result.exitstatus).to be == 0
35
- end.resume
36
- end
37
-
38
- subject.wait do
39
- expect(subject.blocking?).to be_truthy
40
- end
41
- end
42
- end
@@ -1,55 +0,0 @@
1
- # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- RSpec.describe Process do
22
- it "default fork exit status should be 0" do
23
- pid = fork do
24
- end
25
-
26
- Process.waitpid(pid)
27
-
28
- expect($?.exitstatus).to be == 0
29
- end
30
-
31
- it "should fork and return exit status correctly" do
32
- pid = fork do
33
- exit(1)
34
- end
35
-
36
- Process.waitpid(pid)
37
-
38
- expect($?.exitstatus).to be == 1
39
- end
40
-
41
- # This is currently broken on Rubinius.
42
- it "should be okay to use fork within a fiber" do
43
- pid = nil
44
-
45
- Fiber.new do
46
- pid = fork do
47
- exit(2)
48
- end
49
- end.resume
50
-
51
- Process.waitpid(pid)
52
-
53
- expect($?.exitstatus).to be == 2
54
- end
55
- end
@@ -1,99 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "should execute fibers concurrently" do
25
- start_time = Time.now
26
-
27
- Fiber.new do
28
- result = subject.fork { sleep 1.0 }
29
-
30
- expect(result).to be == 0
31
- end.resume
32
-
33
- Fiber.new do
34
- result = subject.fork { sleep 2.0 }
35
-
36
- expect(result).to be == 0
37
- end.resume
38
-
39
- subject.wait
40
-
41
- end_time = Time.now
42
-
43
- # Check that the execution time was roughly 2 seconds:
44
- expect(end_time - start_time).to be_within(0.1).of(2.0)
45
- end
46
-
47
- it "should kill commands" do
48
- start_time = Time.now
49
-
50
- subject.run("sleep 1") do |exit_status|
51
- expect(exit_status).to_not be 0
52
- end
53
-
54
- subject.run("sleep 2") do |exit_status|
55
- expect(exit_status).to_not be 0
56
- end
57
-
58
- subject.wait do
59
- subject.kill(:KILL)
60
- end
61
-
62
- end_time = Time.now
63
-
64
- # Check that processes killed almost immediately:
65
- expect(end_time - start_time).to be < 0.2
66
- end
67
-
68
- it "should pass environment to child process" do
69
- env = {'FOO' => 'BAR'}
70
-
71
- # Make a pipe to receive output from child process:
72
- input, output = IO.pipe
73
-
74
- subject.run(env, "echo $FOO", out: output) do |exit_status|
75
- output.close
76
- end
77
-
78
- subject.wait
79
-
80
- expect(input.read).to be == "BAR\n"
81
- end
82
-
83
- it "should yield exit status" do
84
- start_time = Time.now
85
-
86
- subject.run("sleep 1")
87
-
88
- subject.run("sleep 1") do |exit_status|
89
- expect(exit_status).to be == 0
90
- end
91
-
92
- subject.wait
93
-
94
- end_time = Time.now
95
-
96
- # Check that the execution time was roughly 1 second:
97
- expect(end_time - start_time).to be_within(0.1).of(1.0)
98
- end
99
- end
@@ -1,85 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'process/group'
22
-
23
- RSpec.describe Process::Group do
24
- it "should invoke child task normally" do
25
- start_time = Time.now
26
-
27
- child_exit_status = nil
28
-
29
- subject.wait do
30
- subject.run("exit 0") do |exit_status|
31
- child_exit_status = exit_status
32
- end
33
- end
34
-
35
- expect(child_exit_status).to be == 0
36
- end
37
-
38
- it "should kill child task if process is interrupted" do
39
- start_time = Time.now
40
-
41
- child_exit_status = nil
42
-
43
- expect do
44
- subject.wait do
45
- subject.run("sleep 10") do |exit_status|
46
- child_exit_status = exit_status
47
- end
48
-
49
- # Simulate the parent (controlling) process receiving an interrupt.
50
- raise Interrupt
51
- end
52
- end.to raise_error(Interrupt)
53
-
54
- expect(child_exit_status).to_not be == 0
55
- end
56
-
57
- it "should propagate Interrupt" do
58
- expect(Process::Group).to receive(:new).once.and_call_original
59
-
60
- expect do
61
- Process::Group.wait do |group|
62
- raise Interrupt
63
- end
64
- end.to raise_error(Interrupt)
65
- end
66
-
67
- it "should clear queue after wait" do
68
- subject.limit = 1
69
-
70
- subject.run("sleep 10")
71
- subject.run("sleep 10")
72
-
73
- expect(subject.running?).to be_falsey
74
- expect(subject.queued?).to be_truthy
75
-
76
- expect do
77
- subject.wait do
78
- raise Interrupt
79
- end
80
- end.to raise_error(Interrupt)
81
-
82
- expect(subject.running?).to be_falsey
83
- expect(subject.queued?).to be_falsey
84
- end
85
- end
@@ -1,34 +0,0 @@
1
- # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require "bundler/setup"
22
- require 'covered/rspec'
23
-
24
- RSpec.configure do |config|
25
- # Enable flags like --only-failures and --next-failure
26
- config.example_status_persistence_file_path = ".rspec_status"
27
-
28
- # Disable RSpec exposing methods globally on `Module` and `main`
29
- config.disable_monkey_patching!
30
-
31
- config.expect_with :rspec do |c|
32
- c.syntax = :expect
33
- end
34
- end