process_executer 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +9 -1
- data/lib/process_executer/options.rb +24 -3
- data/lib/process_executer/status.rb +44 -0
- data/lib/process_executer/version.rb +1 -1
- data/lib/process_executer.rb +7 -5
- data/process_executer.gemspec +2 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f568a98075e32879207b26949346e4181eed2d2432c9665e84ddb015d5ded96c
|
4
|
+
data.tar.gz: bcc6f74e77155a251d4ad561495f6edb1b6cf95bccc23b7de7322a0897d4a0af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fc886fade1e486d6acb6c32864a469a6d77700c596dd15a47c4e59e440bfda06b3a1ca506fc4a9be8f7d3bea831525329e735d9cb30d5c01d48395571f9164c
|
7
|
+
data.tar.gz: cab6c4b4d5d1761ac46df3aff8c02c44fed93d071bc6c74fdba802c04175321520c92556c8a43fe79bf3f56d9fb80b82e1b7b60ff50c1bdea8fdcf94bb2e22fd
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,33 @@ All notable changes to the process_executer gem will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## v1.1.0 (2024-02-02)
|
9
|
+
|
10
|
+
[Full Changelog](https://github.com/main-branch/process_executer/compare/v1.0.2..v1.1.0)
|
11
|
+
|
12
|
+
Changes since v1.0.2:
|
13
|
+
|
14
|
+
* a473281 ProcessExecuter.spawn should indicate if the subprocess timed out or not (#43)
|
15
|
+
|
16
|
+
## v1.0.2 (2024-02-01)
|
17
|
+
|
18
|
+
[Full Changelog](https://github.com/main-branch/process_executer/compare/v1.0.1..v1.0.2)
|
19
|
+
|
20
|
+
Changes since v1.0.1:
|
21
|
+
|
22
|
+
* 76ffb91 An invalid timeout value should raise an ArgumentError (#41)
|
23
|
+
* b748819 Release v1.0.1 (#40)
|
24
|
+
|
25
|
+
## v1.0.1 (2024-01-04)
|
26
|
+
|
27
|
+
[Full Changelog](https://github.com/main-branch/process_executer/compare/v1.0.0..v1.0.1)
|
28
|
+
|
29
|
+
Changes since v1.0.0:
|
30
|
+
|
31
|
+
* f434aa1 Add an experimental build for jruby-head on windows (#15)
|
32
|
+
* 97dbcf5 Make updates resulting from doc review (#38)
|
33
|
+
* 93eab18 Release v1.0.0 (#37)
|
34
|
+
|
8
35
|
## v1.0.0 (2023-12-31)
|
9
36
|
|
10
37
|
[Full Changelog](https://github.com/main-branch/process_executer/compare/v0.7.0..v1.0.0)
|
data/README.md
CHANGED
@@ -77,7 +77,15 @@ important behaviorial differences:
|
|
77
77
|
2. A timeout can be specified using the `:timeout` option
|
78
78
|
|
79
79
|
If the command does not terminate before the timeout, the process is killed by
|
80
|
-
sending it the SIGKILL signal.
|
80
|
+
sending it the SIGKILL signal. The returned status object's `timeout?` attribute will
|
81
|
+
return `true`. For example:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
status = ProcessExecuter.spawn('sleep 10', timeout: 0.01)
|
85
|
+
status.signaled? #=> true
|
86
|
+
status.termsig #=> 9
|
87
|
+
status.timeout? #=> true
|
88
|
+
```
|
81
89
|
|
82
90
|
## Installation
|
83
91
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
4
|
require 'ostruct'
|
5
|
+
require 'pp'
|
5
6
|
|
6
7
|
module ProcessExecuter
|
7
8
|
# Validate ProcessExecuter::Executer#spawn options and return Process.spawn options
|
@@ -27,13 +28,14 @@ module ProcessExecuter
|
|
27
28
|
close_others chdir
|
28
29
|
].freeze
|
29
30
|
|
30
|
-
# These options are allowed but should NOT be passed
|
31
|
+
# These options are allowed by `ProcessExecuter.spawn` but should NOT be passed
|
32
|
+
# to `Process.spawn`
|
31
33
|
#
|
32
34
|
NON_SPAWN_OPTIONS = %i[
|
33
35
|
timeout
|
34
36
|
].freeze
|
35
37
|
|
36
|
-
# Any `SPAWN_OPTIONS
|
38
|
+
# Any `SPAWN_OPTIONS` set to `NOT_SET` will not be passed to `Process.spawn`
|
37
39
|
#
|
38
40
|
NOT_SET = :not_set
|
39
41
|
|
@@ -76,7 +78,7 @@ module ProcessExecuter
|
|
76
78
|
# @param options [Hash] Process.spawn options plus additional options listed below.
|
77
79
|
#
|
78
80
|
# See [Process.spawn](https://ruby-doc.org/core/Process.html#method-c-spawn)
|
79
|
-
# for a list of valid.
|
81
|
+
# for a list of valid options that can be passed to `Process.spawn`.
|
80
82
|
#
|
81
83
|
# @option options [Integer, Float, nil] :timeout
|
82
84
|
# Number of seconds to wait for the process to terminate. Any number
|
@@ -86,6 +88,7 @@ module ProcessExecuter
|
|
86
88
|
def initialize(**options)
|
87
89
|
assert_no_unknown_options(options)
|
88
90
|
@options = DEFAULTS.merge(options)
|
91
|
+
assert_timeout_is_valid
|
89
92
|
end
|
90
93
|
|
91
94
|
# Returns the options to be passed to Process.spawn
|
@@ -129,6 +132,24 @@ module ProcessExecuter
|
|
129
132
|
raise ArgumentError, "Unknown options: #{unknown_options.join(', ')}" unless unknown_options.empty?
|
130
133
|
end
|
131
134
|
|
135
|
+
# Raise an error if timeout is not a real non-negative number
|
136
|
+
# @return [void]
|
137
|
+
# @raise [ArgumentError] if timeout is not a real non-negative number
|
138
|
+
# @api private
|
139
|
+
def assert_timeout_is_valid
|
140
|
+
return if @options[:timeout].nil?
|
141
|
+
return if @options[:timeout].is_a?(Numeric) && @options[:timeout].real? && !@options[:timeout].negative?
|
142
|
+
|
143
|
+
raise ArgumentError, invalid_timeout_message
|
144
|
+
end
|
145
|
+
|
146
|
+
# The message to be used when raising an error for an invalid timeout
|
147
|
+
# @return [String]
|
148
|
+
# @api private
|
149
|
+
def invalid_timeout_message
|
150
|
+
"timeout must be nil or a real non-negative number but was #{options[:timeout].pretty_inspect}"
|
151
|
+
end
|
152
|
+
|
132
153
|
# Determine if the given option is a valid option
|
133
154
|
# @param option [Symbol] the option to be tested
|
134
155
|
# @return [Boolean] true if the given option is a valid option
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'delegate'
|
4
|
+
|
5
|
+
module ProcessExecuter
|
6
|
+
# A simple delegator for Process::Status that adds a `timeout?` attribute
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
#
|
10
|
+
class Status < SimpleDelegator
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Create a new Status object from a Process::Status and timeout flag
|
14
|
+
#
|
15
|
+
# @param status [Process::Status] the status to delegate to
|
16
|
+
# @param timeout [Boolean] true if the process timed out
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# status = Process.wait2(pid).last
|
20
|
+
# timeout = false
|
21
|
+
# ProcessExecuter::Status.new(status, timeout)
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
#
|
25
|
+
def initialize(status, timeout)
|
26
|
+
super(status)
|
27
|
+
@timeout = timeout
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!attribute [r] timeout?
|
31
|
+
#
|
32
|
+
# True if the process timed out and was sent the SIGKILL signal
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# status = ProcessExecuter.spawn('sleep 10', timeout: 0.01)
|
36
|
+
# status.timeout? # => true
|
37
|
+
#
|
38
|
+
# @return [Boolean]
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
#
|
42
|
+
def timeout? = @timeout
|
43
|
+
end
|
44
|
+
end
|
data/lib/process_executer.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'process_executer/monitored_pipe'
|
4
4
|
require 'process_executer/options'
|
5
|
+
require 'process_executer/status'
|
5
6
|
|
6
7
|
require 'timeout'
|
7
8
|
|
@@ -12,7 +13,8 @@ require 'timeout'
|
|
12
13
|
module ProcessExecuter
|
13
14
|
# Execute the specified command as a subprocess and return the exit status
|
14
15
|
#
|
15
|
-
# This method blocks until the
|
16
|
+
# This is a convenience method that calls Process.spawn and blocks until the
|
17
|
+
# command has terminated.
|
16
18
|
#
|
17
19
|
# The command will be send the SIGKILL signal if it does not terminate within
|
18
20
|
# the specified timeout.
|
@@ -38,7 +40,7 @@ module ProcessExecuter
|
|
38
40
|
# documentation for valid command and options
|
39
41
|
#
|
40
42
|
# @see ProcessExecuter::Options#initialize See ProcessExecuter::Options#initialize
|
41
|
-
# for
|
43
|
+
# for options that may be specified
|
42
44
|
#
|
43
45
|
# @param command [Array<String>] the command to execute
|
44
46
|
# @param options_hash [Hash] the options to use when exectuting the command
|
@@ -58,16 +60,16 @@ module ProcessExecuter
|
|
58
60
|
# @param pid [Integer] the process id
|
59
61
|
# @param options [ProcessExecuter::Options] the options used
|
60
62
|
#
|
61
|
-
# @return [
|
63
|
+
# @return [ProcessExecuter::Status] the status of the process
|
62
64
|
#
|
63
65
|
# @api private
|
64
66
|
#
|
65
67
|
private_class_method def self.wait_for_process(pid, options)
|
66
68
|
Timeout.timeout(options.timeout) do
|
67
|
-
Process.wait2(pid).last
|
69
|
+
ProcessExecuter::Status.new(Process.wait2(pid).last, false)
|
68
70
|
end
|
69
71
|
rescue Timeout::Error
|
70
72
|
Process.kill('KILL', pid)
|
71
|
-
Process.wait2(pid).last
|
73
|
+
ProcessExecuter::Status.new(Process.wait2(pid).last, true)
|
72
74
|
end
|
73
75
|
end
|
data/process_executer.gemspec
CHANGED
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.metadata['homepage_uri'] = spec.homepage
|
20
20
|
spec.metadata['source_code_uri'] = 'https://github.com/main-branch/process_executer'
|
21
|
-
spec.metadata['changelog_uri'] =
|
21
|
+
spec.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}/file/CHANGELOG.md"
|
22
|
+
spec.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}"
|
22
23
|
|
23
24
|
# Specify which files should be added to the gem when it is released.
|
24
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process_executer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Couball
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler-audit
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/process_executer.rb
|
191
191
|
- lib/process_executer/monitored_pipe.rb
|
192
192
|
- lib/process_executer/options.rb
|
193
|
+
- lib/process_executer/status.rb
|
193
194
|
- lib/process_executer/version.rb
|
194
195
|
- process_executer.gemspec
|
195
196
|
homepage: https://github.com/main-branch/process_executer
|
@@ -199,7 +200,8 @@ metadata:
|
|
199
200
|
allowed_push_host: https://rubygems.org
|
200
201
|
homepage_uri: https://github.com/main-branch/process_executer
|
201
202
|
source_code_uri: https://github.com/main-branch/process_executer
|
202
|
-
changelog_uri: https://rubydoc.info/gems/process_executer/file/CHANGELOG.md
|
203
|
+
changelog_uri: https://rubydoc.info/gems/process_executer/1.1.0/file/CHANGELOG.md
|
204
|
+
documentation_uri: https://rubydoc.info/gems/process_executer/1.1.0
|
203
205
|
rubygems_mfa_required: 'true'
|
204
206
|
post_install_message:
|
205
207
|
rdoc_options: []
|