eventmachine 1.0.0.beta.4-java → 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,7 +29,7 @@ module EventMachine
29
29
  #
30
30
  # # If we don't care about the result:
31
31
  # pool.perform do |dispatcher|
32
- # # The following blcok executes inside a dedicated thread, and should not
32
+ # # The following block executes inside a dedicated thread, and should not
33
33
  # # access EventMachine things:
34
34
  # dispatcher.dispatch do |cassandra|
35
35
  # cassandra.insert(:Things, '10', 'stuff' => 'things')
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.0.beta.4"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -82,7 +82,8 @@ module EventMachine
82
82
  @reactor_running = false
83
83
  @next_tick_queue = []
84
84
  @tails = []
85
- @threadpool = nil
85
+ @threadpool = @threadqueue = @resultqueue = nil
86
+ @all_threads_spawned = false
86
87
 
87
88
  # System errnos
88
89
  # @private
@@ -155,7 +156,13 @@ module EventMachine
155
156
  # will start without release_machine being called and will immediately throw
156
157
 
157
158
  #
158
-
159
+ if reactor_running? and @reactor_pid != Process.pid
160
+ # Reactor was started in a different parent, meaning we have forked.
161
+ # Clean up reactor state so a new reactor boots up in this child.
162
+ stop_event_loop
163
+ release_machine
164
+ @reactor_running = false
165
+ end
159
166
 
160
167
  tail and @tails.unshift(tail)
161
168
 
@@ -169,6 +176,7 @@ module EventMachine
169
176
  @next_tick_queue ||= []
170
177
  @tails ||= []
171
178
  begin
179
+ @reactor_pid = Process.pid
172
180
  @reactor_running = true
173
181
  initialize_event_machine
174
182
  (b = blk || block) and add_timer(0, b)
@@ -201,6 +209,7 @@ module EventMachine
201
209
  @threadqueue = nil
202
210
  @resultqueue = nil
203
211
  @threadpool = nil
212
+ @all_threads_spawned = false
204
213
  end
205
214
 
206
215
  @next_tick_queue = []
@@ -252,7 +261,7 @@ module EventMachine
252
261
  if self.reactor_running?
253
262
  self.stop_event_loop
254
263
  self.release_machine
255
- self.instance_variable_set( '@reactor_running', false )
264
+ @reactor_running = false
256
265
  end
257
266
  self.run block
258
267
  end
@@ -425,7 +434,8 @@ module EventMachine
425
434
  # that you must define. When the network server that is started by
426
435
  # start_server accepts a new connection, it instantiates a new
427
436
  # object of an anonymous class that is inherited from {EventMachine::Connection},
428
- # *into which your handler module have been included*.
437
+ # *into which your handler module have been included*. Arguments passed into start_server
438
+ # after the class name are passed into the constructor during the instantiation.
429
439
  #
430
440
  # Your handler module may override any of the methods in {EventMachine::Connection},
431
441
  # such as {EventMachine::Connection#receive_data}, in order to implement the specific behavior
@@ -736,6 +746,7 @@ module EventMachine
736
746
  c = klass.new s, *args
737
747
 
738
748
  c.instance_variable_set(:@io, io)
749
+ c.instance_variable_set(:@watch_mode, watch_mode)
739
750
  c.instance_variable_set(:@fd, fd)
740
751
 
741
752
  @conns[s] = c
@@ -761,7 +772,11 @@ module EventMachine
761
772
  #raise "still connected" if @conns.has_key?(handler.signature)
762
773
  return handler if @conns.has_key?(handler.signature)
763
774
 
764
- s = connect_server server, port
775
+ s = if port
776
+ connect_server server, port
777
+ else
778
+ connect_unix_server server
779
+ end
765
780
  handler.signature = s
766
781
  @conns[s] = handler
767
782
  block_given? and yield handler
@@ -936,10 +951,21 @@ module EventMachine
936
951
  cback.call result if cback
937
952
  end
938
953
 
939
- @next_tick_mutex.synchronize do
940
- jobs, @next_tick_queue = @next_tick_queue, []
941
- jobs
942
- end.each { |j| j.call }
954
+ # Capture the size at the start of this tick...
955
+ size = @next_tick_mutex.synchronize { @next_tick_queue.size }
956
+ size.times do |i|
957
+ callback = @next_tick_mutex.synchronize { @next_tick_queue.shift }
958
+ begin
959
+ callback.call
960
+ ensure
961
+ # This is a little nasty. The problem is, if an exception occurs during
962
+ # the callback, then we need to send a signal to the reactor to actually
963
+ # do some work during the next_tick. The only mechanism we have from the
964
+ # ruby side is next_tick itself, although ideally, we'd just drop a byte
965
+ # on the loopback descriptor.
966
+ EM.next_tick {} if $!
967
+ end
968
+ end
943
969
  end
944
970
 
945
971
 
@@ -991,7 +1017,6 @@ module EventMachine
991
1017
  # has no constructor.
992
1018
 
993
1019
  unless @threadpool
994
- require 'thread'
995
1020
  @threadpool = []
996
1021
  @threadqueue = ::Queue.new
997
1022
  @resultqueue = ::Queue.new
@@ -1016,6 +1041,19 @@ module EventMachine
1016
1041
  end
1017
1042
  @threadpool << thread
1018
1043
  end
1044
+ @all_threads_spawned = true
1045
+ end
1046
+
1047
+ ##
1048
+ # Returns +true+ if all deferred actions are done executing and their
1049
+ # callbacks have been fired.
1050
+ #
1051
+ def self.defers_finished?
1052
+ return false if @threadpool and !@all_threads_spawned
1053
+ return false if @threadqueue and not @threadqueue.empty?
1054
+ return false if @resultqueue and not @resultqueue.empty?
1055
+ return false if @threadpool and @threadqueue.num_waiting != @threadpool.size
1056
+ return true
1019
1057
  end
1020
1058
 
1021
1059
  class << self
@@ -1391,11 +1429,19 @@ module EventMachine
1391
1429
  if opcode == ConnectionUnbound
1392
1430
  if c = @conns.delete( conn_binding )
1393
1431
  begin
1394
- if c.original_method(:unbind).arity == 1
1432
+ if c.original_method(:unbind).arity != 0
1395
1433
  c.unbind(data == 0 ? nil : EventMachine::ERRNOS[data])
1396
1434
  else
1397
1435
  c.unbind
1398
1436
  end
1437
+ # If this is an attached (but not watched) connection, close the underlying io object.
1438
+ if c.instance_variable_defined?(:@io) and !c.instance_variable_get(:@watch_mode)
1439
+ io = c.instance_variable_get(:@io)
1440
+ begin
1441
+ io.close
1442
+ rescue Errno::EBADF, IOError
1443
+ end
1444
+ end
1399
1445
  rescue
1400
1446
  @wrapped_exception = $!
1401
1447
  stop
@@ -203,6 +203,11 @@ module EventMachine
203
203
  Socket.pack_sockaddr_in(*peer)
204
204
  end
205
205
  end
206
+ def self.get_sockname sig
207
+ if sockName = @em.getSockName(sig)
208
+ Socket.pack_sockaddr_in(*sockName)
209
+ end
210
+ end
206
211
  # @private
207
212
  def self.attach_fd fileno, watch_mode
208
213
  # 3Aug09: We could pass in the actual SocketChannel, but then it would be modified (set as non-blocking), and
File without changes
@@ -23,7 +23,7 @@ else
23
23
  def setup_cross_compilation(ext)
24
24
  unless RUBY_PLATFORM =~ /mswin|mingw/
25
25
  ext.cross_compile = true
26
- ext.cross_platform = ['x86-mingw32']#, 'x86-mswin32-60']
26
+ ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60']
27
27
 
28
28
  # inject 1.8/1.9 pure-ruby entry point
29
29
  ext.cross_compiling do |spec|
File without changes
@@ -224,4 +224,71 @@ class TestBasic < Test::Unit::TestCase
224
224
  end
225
225
  end
226
226
  end
227
+
228
+ def test_schedule_close
229
+ localhost, port = '127.0.0.1', 9000
230
+ timer_ran = false
231
+ num_close_scheduled = nil
232
+ EM.run do
233
+ assert_equal 0, EM.num_close_scheduled
234
+ EM.add_timer(1) { timer_ran = true; EM.stop }
235
+ EM.start_server localhost, port do |s|
236
+ s.close_connection
237
+ num_close_scheduled = EM.num_close_scheduled
238
+ end
239
+ EM.connect localhost, port do |c|
240
+ def c.unbind
241
+ EM.stop
242
+ end
243
+ end
244
+ end
245
+ assert !timer_ran
246
+ assert_equal 1, num_close_scheduled
247
+ end
248
+
249
+ def test_fork_safe
250
+ return unless cpid = fork { exit! } rescue false
251
+
252
+ read, write = IO.pipe
253
+ EM.run do
254
+ cpid = fork do
255
+ write.puts "forked"
256
+ EM.run do
257
+ EM.next_tick do
258
+ write.puts "EM ran"
259
+ exit!
260
+ end
261
+ end
262
+ end
263
+ EM.stop
264
+ end
265
+ Process.waitall
266
+ assert_equal "forked\n", read.readline
267
+ assert_equal "EM ran\n", read.readline
268
+ ensure
269
+ read.close rescue nil
270
+ write.close rescue nil
271
+ end
272
+
273
+ def test_error_handler_idempotent # issue 185
274
+ errors = []
275
+ ticks = []
276
+ EM.error_handler do |e|
277
+ errors << e
278
+ end
279
+
280
+ EM.run do
281
+ EM.next_tick do
282
+ ticks << :first
283
+ raise
284
+ end
285
+ EM.next_tick do
286
+ ticks << :second
287
+ end
288
+ EM.add_timer(0.001) { EM.stop }
289
+ end
290
+
291
+ assert_equal 1, errors.size
292
+ assert_equal [:first, :second], ticks
293
+ end
227
294
  end
@@ -0,0 +1,23 @@
1
+ require 'em_test_helper'
2
+
3
+ class TestIdleConnection < Test::Unit::TestCase
4
+ if EM.respond_to?(:get_idle_time)
5
+ def test_idle_time
6
+ EM.run{
7
+ conn = EM.connect 'www.google.com', 80
8
+ EM.add_timer(3){
9
+ $idle_time = conn.get_idle_time
10
+ conn.send_data "GET / HTTP/1.0\r\n\r\n"
11
+ EM.next_tick{
12
+ $idle_time_after_send = conn.get_idle_time
13
+ conn.close_connection
14
+ EM.stop
15
+ }
16
+ }
17
+ }
18
+
19
+ assert_in_delta 3, $idle_time, 0.2
20
+ assert_equal 0, $idle_time_after_send
21
+ end
22
+ end
23
+ end
@@ -115,6 +115,41 @@ class TestPool < Test::Unit::TestCase
115
115
  assert_equal [:res], pool.contents
116
116
  end
117
117
 
118
+ def test_contents_when_perform_errors_and_on_error_is_not_set
119
+ pool.add :res
120
+ assert_equal [:res], pool.contents
121
+
122
+ pool.perform do |r|
123
+ d = EM::DefaultDeferrable.new
124
+ d.fail
125
+ d
126
+ end
127
+
128
+ EM.run { EM.next_tick { EM.stop } }
129
+
130
+ assert_equal [:res], pool.contents
131
+ end
132
+
133
+ def test_contents_when_perform_errors_and_on_error_is_set
134
+ pool.add :res
135
+ res = nil
136
+ pool.on_error do |r|
137
+ res = r
138
+ end
139
+ assert_equal [:res], pool.contents
140
+
141
+ pool.perform do |r|
142
+ d = EM::DefaultDeferrable.new
143
+ d.fail 'foo'
144
+ d
145
+ end
146
+
147
+ EM.run { EM.next_tick { EM.stop } }
148
+
149
+ assert_equal :res, res
150
+ assert_equal [], pool.contents
151
+ end
152
+
118
153
  def test_num_waiting
119
154
  pool.add :res
120
155
  assert_equal 0, pool.num_waiting
@@ -125,4 +160,35 @@ class TestPool < Test::Unit::TestCase
125
160
  assert_equal 10, pool.num_waiting
126
161
  end
127
162
 
128
- end
163
+ def test_exceptions_in_the_work_block_bubble_up_raise_and_fail_the_resource
164
+ pool.add :res
165
+
166
+ res = nil
167
+ pool.on_error { |r| res = r }
168
+ pool.perform { raise 'boom' }
169
+
170
+ assert_raises(RuntimeError) do
171
+ EM.run { EM.next_tick { EM.stop } }
172
+ end
173
+
174
+ assert_equal [], pool.contents
175
+ assert_equal :res, res
176
+ end
177
+
178
+ def test_removed_list_does_not_leak_on_errors
179
+ pool.add :res
180
+
181
+ pool.on_error do |r|
182
+ # This is actually the wrong thing to do, and not required, but some users
183
+ # might do it. When they do, they would find that @removed would cause a
184
+ # slow leak.
185
+ pool.remove r
186
+ end
187
+
188
+ pool.perform { d = EM::DefaultDeferrable.new; d.fail; d }
189
+
190
+ EM.run { EM.next_tick { EM.stop } }
191
+ assert_equal [], pool.instance_variable_get(:@removed)
192
+ end
193
+
194
+ end
@@ -24,6 +24,7 @@ class TestProxyConnection < Test::Unit::TestCase
24
24
  end
25
25
 
26
26
  def unbind
27
+ $proxied_bytes = self.get_proxied_bytes
27
28
  @client.close_connection_after_writing
28
29
  end
29
30
  end
@@ -94,7 +95,7 @@ class TestProxyConnection < Test::Unit::TestCase
94
95
  end
95
96
 
96
97
  def receive_data(data)
97
- EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
98
+ @proxy = EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
98
99
  end
99
100
  end
100
101
 
@@ -134,6 +135,17 @@ class TestProxyConnection < Test::Unit::TestCase
134
135
  assert_equal("I know!", $client_data)
135
136
  end
136
137
 
138
+ def test_proxied_bytes
139
+ EM.run {
140
+ EM.start_server("127.0.0.1", @port, Server)
141
+ EM.start_server("127.0.0.1", @proxy_port, ProxyServer, @port)
142
+ EM.connect("127.0.0.1", @proxy_port, Client)
143
+ }
144
+
145
+ assert_equal("I know!", $client_data)
146
+ assert_equal("I know!".bytesize, $proxied_bytes)
147
+ end
148
+
137
149
  def test_partial_proxy_connection
138
150
  EM.run {
139
151
  EM.start_server("127.0.0.1", @port, Server)
@@ -2,6 +2,15 @@ require 'em_test_helper'
2
2
  require 'socket'
3
3
 
4
4
  class TestUnbindReason < Test::Unit::TestCase
5
+
6
+ class StubConnection < EM::Connection
7
+ attr_reader :error
8
+ def unbind(reason = nil)
9
+ @error = reason
10
+ EM.stop
11
+ end
12
+ end
13
+
5
14
  def test_connect_timeout
6
15
  error = nil
7
16
  EM.run {
@@ -13,7 +22,7 @@ class TestUnbindReason < Test::Unit::TestCase
13
22
  }
14
23
  conn.pending_connect_timeout = 0.1
15
24
  }
16
- assert_equal error, Errno::ETIMEDOUT
25
+ assert_equal Errno::ETIMEDOUT, error
17
26
  end
18
27
 
19
28
  def test_connect_refused
@@ -26,6 +35,14 @@ class TestUnbindReason < Test::Unit::TestCase
26
35
  end
27
36
  }
28
37
  }
29
- assert_equal error, Errno::ECONNREFUSED
38
+ assert_equal Errno::ECONNREFUSED, error
39
+ end
40
+
41
+ def test_optional_argument
42
+ conn = nil
43
+ EM.run {
44
+ conn = EM.connect '127.0.0.1', 12388, StubConnection
45
+ }
46
+ assert_equal Errno::ECONNREFUSED, conn.error
30
47
  end
31
48
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventmachine
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 1.0.0.beta.4
4
+ prerelease:
5
+ version: 1.0.0
6
6
  platform: java
7
7
  authors:
8
8
  - Francis Cianfrocca
@@ -11,8 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-09-15 00:00:00 -07:00
15
- default_executable:
14
+ date: 2012-09-08 00:00:00 Z
16
15
  dependencies:
17
16
  - !ruby/object:Gem::Dependency
18
17
  name: rake-compiler
@@ -20,9 +19,9 @@ dependencies:
20
19
  requirement: &id001 !ruby/object:Gem::Requirement
21
20
  none: false
22
21
  requirements:
23
- - - "="
22
+ - - ~>
24
23
  - !ruby/object:Gem::Version
25
- version: 0.7.9
24
+ version: 0.8.1
26
25
  type: :development
27
26
  version_requirements: *id001
28
27
  - !ruby/object:Gem::Dependency
@@ -186,9 +185,9 @@ files:
186
185
  - lib/em/version.rb
187
186
  - lib/eventmachine.rb
188
187
  - lib/jeventmachine.rb
189
- - tasks/cpp.rake_example
190
- - tasks/package.rake
191
- - tasks/test.rake
188
+ - rakelib/cpp.rake_example
189
+ - rakelib/package.rake
190
+ - rakelib/test.rake
192
191
  - tests/client.crt
193
192
  - tests/client.key
194
193
  - tests/em_test_helper.rb
@@ -209,6 +208,7 @@ files:
209
208
  - tests/test_hc.rb
210
209
  - tests/test_httpclient.rb
211
210
  - tests/test_httpclient2.rb
211
+ - tests/test_idle_connection.rb
212
212
  - tests/test_inactivity_timeout.rb
213
213
  - tests/test_kb.rb
214
214
  - tests/test_ltp.rb
@@ -242,7 +242,6 @@ files:
242
242
  - tests/test_ud.rb
243
243
  - tests/test_unbind_reason.rb
244
244
  - lib/rubyeventmachine.jar
245
- has_rdoc: true
246
245
  homepage: http://rubyeventmachine.com
247
246
  licenses: []
248
247
 
@@ -267,13 +266,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
267
266
  required_rubygems_version: !ruby/object:Gem::Requirement
268
267
  none: false
269
268
  requirements:
270
- - - ">"
269
+ - - ">="
271
270
  - !ruby/object:Gem::Version
272
- version: 1.3.1
271
+ version: "0"
273
272
  requirements: []
274
273
 
275
274
  rubyforge_project: eventmachine
276
- rubygems_version: 1.5.1
275
+ rubygems_version: 1.8.15
277
276
  signing_key:
278
277
  specification_version: 3
279
278
  summary: Ruby/EventMachine library