ztk 1.16.2 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzM4ZjAxYThhZjBkZDc2NTQ3MDhjYTlmYmYwYjUzNGIzMmQ4ZmIwYw==
4
+ YzBhZGNmNmVjYzgxMzk1MWI4MTBmMzE2ZTViMjVjYmY1NGUzMDc3ZA==
5
5
  data.tar.gz: !binary |-
6
- NDllOTBjMjdjNzc2ZWVkYWE1Yzk5ODA3YWNkMzMzOTI1YTRlY2I0MQ==
6
+ ZGFkMjAxZGVmNDg3ZjRkODI0OWIxMTRhODA2ZmMzNDlhNTgzOGQyMQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmJkNzI3NzFlMWNhNmNlMGIzNzM2NTcwYzc1OTIxZGQzMTcxZjUzNTk1MWVl
10
- ZTFhNzI5Mjc5MTFjOTkxODUyZGY3NWNjODg5NTU2YzBlNmNiZWRlZWM5ZDgx
11
- MmNmMDZiM2Q1ZTYxMzIzOTVhMmE1MDQ3ZDMyMmUwMTc3MjFmZDA=
9
+ YjQzNDdkYzQxYmZlOGYzNWViZjRkZTlmODQ2MWE3MDcxNTdjZmQ1MWEzODg4
10
+ ZDU4ODI3MWZjYTA0NDlhODIyMjEwMjY1ZWRlOThhZDg4YmI3YmM2YWRjZDVh
11
+ YWE5NzU0ZGQzNTU0ZGYxMzU2NjQ4MTRjYmZmYWZkYmZjNmI5M2U=
12
12
  data.tar.gz: !binary |-
13
- NDM3YjEwODQ0ZWRmMGZkYTU2N2ZjMWNjZTc5ZmU5NGY3NTU4YzFhMTFjY2Nm
14
- ODk4MTZiNWYxYjhjZjIwZWQxMDQyYmNlZmRiZTM1M2EzY2JhZWU1OTY2Mzdi
15
- NjUwNWRjMmNmMjZmNTZhMzIwZWIyMTY2OTI1ZWZjYjhmZjMyZjM=
13
+ MzFlYzc2NDVlYTkxN2Y1NTNmMzk1ODdmMzMzZThjOWIwMzM1MTdiZDYzMzI2
14
+ NDNlYmQxN2E3ZmRkNjdjYzVlMjQxMmNlNWQ2YjYxOThjZGZkZmMwMjkzYWJh
15
+ MGQyMzUwMGNlMDlhOGQxMTdjYTFmZDM0MWU1NTBhMzFkNWQ0Nzc=
@@ -96,6 +96,20 @@ module ZTK
96
96
  # @author Zachary Patten <zachary AT jovelabs DOT com>
97
97
  class Parallel < ZTK::Base
98
98
 
99
+ class Break < ParallelError; end
100
+
101
+ # Tests if we can marshal an exception via the results; otherwise creates
102
+ # an exception we can marshal.
103
+ class ExceptionWrapper
104
+ attr_reader :exception
105
+
106
+ def initialize(exception)
107
+ dumpable = (Marshal.dump(exception) rescue nil)
108
+ dumpable.nil? and (exception = RuntimeError.new(exception.inspect))
109
+ @exception = exception
110
+ end
111
+ end
112
+
99
113
  # Default Maximum Number of Forks
100
114
  MAX_FORKS = case RUBY_PLATFORM
101
115
  when /darwin/ then
@@ -129,6 +143,15 @@ module ZTK
129
143
  @forks = Array.new
130
144
  @results = Array.new
131
145
  GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
146
+
147
+ %w( kill term int hup ).map(&:upcase).each do |signal|
148
+ Signal.trap(signal) do
149
+ $stderr.puts("SIG#{signal} received by PID##{Process.pid}; aborting parallel executing...")
150
+
151
+ signal_all(signal)
152
+ exit!(1)
153
+ end
154
+ end
132
155
  end
133
156
 
134
157
  # Process in parallel.
@@ -151,18 +174,27 @@ module ZTK
151
174
 
152
175
  config.before_fork and config.before_fork.call(Process.pid)
153
176
  pid = Process.fork do
177
+
154
178
  config.after_fork and config.after_fork.call(Process.pid)
155
179
 
156
180
  parent_writer.close
157
181
  parent_reader.close
158
182
 
159
- if !(data = block.call).nil?
183
+ data = nil
184
+ begin
185
+ data = block.call
186
+ rescue Exception => e
187
+ data = ExceptionWrapper.new(e)
188
+ end
189
+
190
+ if !data.nil?
160
191
  config.ui.logger.debug { "write(#{data.inspect})" }
161
192
  child_writer.write(Base64.encode64(Marshal.dump(data)))
162
193
  end
163
194
 
164
195
  child_reader.close
165
196
  child_writer.close
197
+
166
198
  Process.exit!(0)
167
199
  end
168
200
  config.after_fork and config.after_fork.call(Process.pid)
@@ -188,10 +220,14 @@ module ZTK
188
220
  config.ui.logger.debug { "wait" }
189
221
  config.ui.logger.debug { "forks(#{@forks.inspect})" }
190
222
  pid, status = (Process.wait2(-1) rescue nil)
223
+
191
224
  if !pid.nil? && !status.nil? && !(fork = @forks.select{ |f| f[:pid] == pid }.first).nil?
192
225
  data = (Marshal.load(Base64.decode64(fork[:reader].read.to_s)) rescue nil)
193
226
  config.ui.logger.debug { "read(#{data.inspect})" }
227
+
228
+ process_exception_data(data)
194
229
  !data.nil? and @results.push(data)
230
+
195
231
  fork[:reader].close
196
232
  fork[:writer].close
197
233
 
@@ -212,6 +248,24 @@ module ZTK
212
248
  @results
213
249
  end
214
250
 
251
+ # Signals all forks.
252
+ #
253
+ # @return [Integer] The number of processes signaled.
254
+ def signal_all(signal="KILL")
255
+ signaled = 0
256
+ if (!@forks.nil? && (@forks.count > 0))
257
+ @forks.each do |fork|
258
+ begin
259
+ Process.kill(signal, fork[:pid])
260
+ signaled += 1
261
+ rescue
262
+ nil
263
+ end
264
+ end
265
+ end
266
+ signaled
267
+ end
268
+
215
269
  # Count of active forks.
216
270
  #
217
271
  # @return [Integer] Current number of active forks.
@@ -220,6 +274,18 @@ module ZTK
220
274
  @forks.count
221
275
  end
222
276
 
277
+
278
+ private
279
+
280
+ def process_exception_data(data)
281
+ return if !(ZTK::Parallel::ExceptionWrapper === data)
282
+
283
+ config.ui.logger.fatal { "exception(#{data.exception.inspect})" }
284
+
285
+ signal_all
286
+ raise data.exception
287
+ end
288
+
223
289
  end
224
290
 
225
291
  end
@@ -1,6 +1,6 @@
1
1
  module ZTK
2
2
 
3
3
  # ZTK Version String
4
- VERSION = "1.16.2"
4
+ VERSION = "1.17.0"
5
5
 
6
6
  end
@@ -22,7 +22,10 @@ require "spec_helper"
22
22
 
23
23
  describe ZTK::Parallel do
24
24
 
25
- subject { ZTK::Parallel.new }
25
+ subject {
26
+ ui = ZTK::UI.new(:logger => $logger)
27
+ ZTK::Parallel.new(:ui => ui)
28
+ }
26
29
 
27
30
  describe "class" do
28
31
 
@@ -56,6 +59,26 @@ describe ZTK::Parallel do
56
59
  subject.results.include?(Process.pid).should be false
57
60
  end
58
61
 
62
+ it "should stop all execution when the ZTK::Parallel::Break exception is raised" do
63
+ 3.times do |x|
64
+ subject.process do
65
+ raise ZTK::Parallel::Break
66
+ end
67
+ end
68
+
69
+ lambda { subject.waitall }.should raise_error
70
+ end
71
+
72
+ it "should stop all execution when any exception is raised" do
73
+ 3.times do |x|
74
+ subject.process do
75
+ raise "SomeException"
76
+ end
77
+ end
78
+
79
+ lambda { subject.waitall }.should raise_error
80
+ end
81
+
59
82
  end
60
83
 
61
84
  describe "#wait" do
@@ -67,7 +90,7 @@ describe ZTK::Parallel do
67
90
  end
68
91
  end
69
92
 
70
- 3.times do
93
+ while subject.count > 0 do
71
94
  subject.wait
72
95
  end
73
96
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ztk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.2
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Patten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-03 00:00:00.000000000 Z
11
+ date: 2014-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport