libis-tools 0.9.60 → 0.9.62

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
  SHA1:
3
- metadata.gz: 849924a2ded64d5bdf008c008bfef08c7147ed86
4
- data.tar.gz: de30bd5fdb3957bfb2065859be5dfbe21acf211a
3
+ metadata.gz: a2464bf3e02e56791cd56ff6c266ab875fec58b5
4
+ data.tar.gz: cbef32af7fde215e0b7cf2b3e8f1ca4d0c5609b9
5
5
  SHA512:
6
- metadata.gz: c38376b193fa67a9258bb1ee42e3635627a10e1b271946f134b2a425eb86bd154e29603de52f15e1c22126042afd104f220a4f5ff65606a702a8b040b90aac99
7
- data.tar.gz: 77a2529dc92b94c6cc8395363cd3ea133a9ccdc1c8061f6164f28917aed932a84f600675f5b229ed989ac109ea684e2a5cbdfecef73fa884bd36b900669f48f4
6
+ metadata.gz: 94c9e9154bfdb7b56ef646dded3b31031f8011c01a1cfd9e6f15e23349a680bcecb984734da1a383663993e0ae69c36b066f9b71364d4b39842645cd33e65e47
7
+ data.tar.gz: d67f4c5487a564cf9d24a55fd500017706d669caa3b7d7667ddf2767e3f4430d99051993073531cbad57a053f52be0860097cd94b2ed66947f90d58d18f8c1ea
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- require 'open3'
2
+ require 'timeout'
3
3
 
4
4
  module Libis
5
5
  module Tools
@@ -10,6 +10,17 @@ module Libis
10
10
  # * :out => an array with lines that were printed on the external program's standard out.
11
11
  # * :err => an array with lines that were printed on the external program's standard error.
12
12
  # * :status => exit code returned by the external program.
13
+ # * :timeout => true if the command was terminated due to a timeout.
14
+ # * :pid => pid of the command (in case <pid>.log files need to be cleaned up)
15
+ #
16
+ # Optionally an option hash can be appended to the list of arguments with:
17
+ # * :stdin_data => values sent to the command's standard input (optional, nothing sent if not present)
18
+ # * :binmode => if present and true, will set the IO communication to binary data
19
+ # * :timeout => if specified, SIGTERM signal is sent to the command after the number of seconds
20
+ # * :signal => Signal sent to the command instead of the default SIGTERM
21
+ # * :kill_after => if specified, SIGKILL signal is sent aftern the number of seconds if command is still running
22
+ # after initial signal was sent
23
+ # * any other options will be handed over to the spawn command (e.g. pgroup)
13
24
  #
14
25
  # Examples:
15
26
  #
@@ -30,32 +41,92 @@ module Libis
30
41
  # Run an external program and return status, stdout and stderr.
31
42
  #
32
43
  #
33
- # @param [String] cmd program name
34
- # @param [Array<String>] opts optional list of command line arguments
44
+ # @param [Array<String>] cmd command name optionally prepended with env and appended with command-line arguments
35
45
  # @return [Hash] a Hash with:
36
46
  # * :status (Integer) - the exit status of the command
37
47
  # * :out (Array<String>) - the stdout output of the command
38
48
  # * :err (Array<String>)- the stderr output of the command
39
- def self.run(cmd, *opts)
49
+ # * :timeout(Boolean) - if true, the command did not return in time
50
+ # * :pid(Integer) - the command's processID
51
+ def self.run(*cmd)
52
+
53
+ spawn_opts = Hash === cmd.last ? cmd.pop.dup : {}
54
+ opts = {
55
+ :stdin_data => spawn_opts.delete(:stdin_data) || '',
56
+ :binmode => spawn_opts.delete(:binmode) || false,
57
+ :timeout => spawn_opts.delete(:timeout),
58
+ :signal => spawn_opts.delete(:signal) || :TERM,
59
+ :kill_after => spawn_opts.delete(:kill_after),
60
+ }
61
+ in_r, in_w = IO.pipe
62
+ out_r, out_w = IO.pipe
63
+ err_r, err_w = IO.pipe
64
+ in_w.sync = true
65
+
66
+ if opts[:binmode]
67
+ in_w.binmode
68
+ out_r.binmode
69
+ err_r.binmode
70
+ end
71
+
72
+ spawn_opts[:in] = in_r
73
+ spawn_opts[:out] = out_w
74
+ spawn_opts[:err] = err_w
75
+
40
76
  result = {
41
- status: 999,
42
- out: [],
43
- err: []
77
+ :pid => nil,
78
+ :status => nil,
79
+ :out => [],
80
+ :err => [],
81
+ :timeout => false,
44
82
  }
83
+
84
+ out_reader = nil
85
+ err_reader = nil
86
+ wait_thr = nil
87
+
45
88
  begin
46
- output, error, status = Open3.capture3(cmd, *opts)
47
- result[:out] = output.split("\n").map(&:chomp)
48
- result[:err] = error.split("\n").map(&:chomp)
49
- result[:status] = status.exitstatus
89
+ Timeout.timeout(opts[:timeout]) do
90
+ result[:pid] = spawn(*cmd, spawn_opts)
91
+ wait_thr = Process.detach(result[:pid])
92
+ in_r.close
93
+ out_w.close
94
+ err_w.close
95
+
96
+ out_reader = Thread.new {out_r.read}
97
+ err_reader = Thread.new {err_r.read}
98
+
99
+ in_w.write opts[:stdin_data]
100
+ in_w.close
101
+
102
+ result[:status] = wait_thr.value
103
+ end
104
+
105
+ rescue Timeout::Error
106
+ result[:timeout] = true
107
+ pid = spawn_opts[:pgroup] ? -result[:pid] : result[:pid]
108
+ Process.kill(opts[:signal], pid)
109
+ if opts[:kill_after]
110
+ unless wait_thr.join(opts[:kill_after])
111
+ Process.kill(:KILL, pid)
112
+ end
113
+ end
50
114
 
51
115
  rescue StandardError => e
52
116
  result[:err] = [e.class.name, e.message]
53
117
 
118
+ ensure
119
+ result[:status] = wait_thr.value.exitstatus if wait_thr
120
+ result[:out] += out_reader.value.split("\n").map(&:chomp) if out_reader
121
+ result[:err] += err_reader.value.split("\n").map(&:chomp) if err_reader
122
+ out_r.close unless out_r.closed?
123
+ err_r.close unless err_r.closed?
54
124
  end
55
125
 
56
126
  result
57
127
 
58
128
  end
129
+
59
130
  end
60
131
 
61
132
  end
@@ -240,11 +240,7 @@ module Libis
240
240
 
241
241
  def get_id(klass)
242
242
  self.mutex.synchronize do
243
- if @id_map[klass]
244
- @id_map[klass] += 1
245
- else
246
- @id_map[klass] = 1
247
- end
243
+ @id_map[klass] = (@id_map[klass] ? @id_map[klass] + 1 : 1)
248
244
  return @id_map[klass]
249
245
  end
250
246
  end
@@ -1,4 +1,5 @@
1
1
  require 'libis/tools/thread_safe'
2
+ require 'uri'
2
3
 
3
4
  module Libis
4
5
  module Tools
@@ -280,9 +281,9 @@ module Libis
280
281
  compositionLevel: composition_level,
281
282
  # fileLocationType: 'FILE',
282
283
  # fileLocation: '',
283
- fileOriginalName: orig_name,
284
- fileOriginalPath: orig_path,
285
- fileOriginalID: location,
284
+ fileOriginalName: URI.encode(orig_name),
285
+ fileOriginalPath: URI.encode(orig_path),
286
+ fileOriginalID: URI.encode(location),
286
287
  fileExtension: ::File.extname(orig_name),
287
288
  fileMIMEType: mimetype,
288
289
  fileSizeBytes: size,
@@ -1,5 +1,5 @@
1
1
  module Libis
2
2
  module Tools
3
- VERSION = '0.9.60'
3
+ VERSION = '0.9.62'
4
4
  end
5
5
  end
data/spec/command_spec.rb CHANGED
@@ -61,4 +61,27 @@ describe 'Command' do
61
61
 
62
62
  end
63
63
 
64
+ it 'should allow to supply input data' do
65
+
66
+ result = Libis::Tools::Command.run('cat', stdin_data: "FooBar", timeout: 1)
67
+ expect(result[:out]).to eq ['FooBar']
68
+ expect(result[:err].size).to eq 0
69
+ expect(result[:status]).to eq 0
70
+
71
+ end
72
+
73
+ it 'should not timeout if command finishes' do
74
+
75
+ result = Libis::Tools::Command.run('cat', stdin_data: "FooBar", timeout: 1)
76
+ expect(result[:timeout]).to be_falsey
77
+
78
+ end
79
+
80
+ it 'should timeout if command hangs' do
81
+
82
+ result = Libis::Tools::Command.run('ls', '-aRlp', '/', timeout: 1)
83
+ expect(result[:timeout]).to be_truthy
84
+
85
+ end
86
+
64
87
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libis-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.60
4
+ version: 0.9.62
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kris Dekeyser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-22 00:00:00.000000000 Z
11
+ date: 2018-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler