eventmachine 1.0.9.1-java → 1.2.0.1-java

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +2 -2
  4. data/ext/cmain.cpp +77 -5
  5. data/ext/ed.cpp +112 -42
  6. data/ext/ed.h +27 -13
  7. data/ext/em.cpp +105 -163
  8. data/ext/em.h +10 -7
  9. data/ext/eventmachine.h +13 -1
  10. data/ext/extconf.rb +23 -14
  11. data/ext/fastfilereader/extconf.rb +1 -2
  12. data/ext/fastfilereader/rubymain.cpp +6 -6
  13. data/ext/project.h +9 -4
  14. data/ext/rubymain.cpp +155 -36
  15. data/ext/ssl.cpp +157 -13
  16. data/ext/ssl.h +7 -2
  17. data/lib/em/channel.rb +5 -0
  18. data/lib/em/completion.rb +2 -2
  19. data/lib/em/connection.rb +61 -3
  20. data/lib/em/iterator.rb +26 -5
  21. data/lib/em/pool.rb +1 -1
  22. data/lib/em/protocols/line_and_text.rb +1 -1
  23. data/lib/em/pure_ruby.rb +6 -1
  24. data/lib/em/queue.rb +16 -7
  25. data/lib/em/resolver.rb +46 -23
  26. data/lib/em/threaded_resource.rb +2 -2
  27. data/lib/em/version.rb +1 -1
  28. data/lib/eventmachine.rb +59 -42
  29. data/lib/rubyeventmachine.jar +0 -0
  30. data/rakelib/package.rake +23 -1
  31. data/tests/dhparam.pem +13 -0
  32. data/tests/em_test_helper.rb +79 -0
  33. data/tests/test_basic.rb +17 -26
  34. data/tests/test_channel.rb +14 -1
  35. data/tests/test_connection_write.rb +2 -2
  36. data/tests/test_defer.rb +17 -0
  37. data/tests/test_epoll.rb +1 -1
  38. data/tests/test_fork.rb +75 -0
  39. data/tests/test_ipv4.rb +125 -0
  40. data/tests/test_ipv6.rb +131 -0
  41. data/tests/test_iterator.rb +18 -0
  42. data/tests/test_many_fds.rb +1 -1
  43. data/tests/test_queue.rb +14 -0
  44. data/tests/test_resolver.rb +23 -0
  45. data/tests/test_set_sock_opt.rb +2 -0
  46. data/tests/test_ssl_dhparam.rb +83 -0
  47. data/tests/test_ssl_ecdh_curve.rb +79 -0
  48. data/tests/test_ssl_extensions.rb +49 -0
  49. data/tests/test_ssl_methods.rb +19 -0
  50. data/tests/test_ssl_protocols.rb +246 -0
  51. data/tests/test_ssl_verify.rb +44 -0
  52. data/tests/test_system.rb +4 -0
  53. data/tests/test_unbind_reason.rb +5 -1
  54. metadata +101 -20
  55. data/.gitignore +0 -21
  56. data/.travis.yml +0 -22
  57. data/.yardopts +0 -7
  58. data/Gemfile +0 -2
  59. data/Rakefile +0 -20
  60. data/eventmachine.gemspec +0 -38
  61. data/rakelib/cpp.rake_example +0 -77
data/lib/em/pool.rb CHANGED
@@ -143,7 +143,7 @@ module EventMachine
143
143
  else
144
144
  raise ArgumentError, "deferrable expected from work"
145
145
  end
146
- rescue Exception
146
+ rescue
147
147
  failure resource
148
148
  raise
149
149
  end
@@ -45,7 +45,7 @@ module EventMachine
45
45
  @lpb_buffer.extract(data).each do |line|
46
46
  receive_line(line.chomp) if respond_to?(:receive_line)
47
47
  end
48
- rescue Exception
48
+ rescue
49
49
  receive_error('overlength line') if respond_to?(:receive_error)
50
50
  close_connection
51
51
  return
data/lib/em/pure_ruby.rb CHANGED
@@ -66,6 +66,11 @@ module EventMachine
66
66
  def release_machine
67
67
  end
68
68
 
69
+
70
+ def stopping?
71
+ return Reactor.instance.stop_scheduled
72
+ end
73
+
69
74
  # @private
70
75
  def stop
71
76
  Reactor.instance.stop
@@ -273,7 +278,7 @@ module EventMachine
273
278
 
274
279
  HeartbeatInterval = 2
275
280
 
276
- attr_reader :current_loop_time
281
+ attr_reader :current_loop_time, :stop_scheduled
277
282
 
278
283
  def initialize
279
284
  initialize_for_run
data/lib/em/queue.rb CHANGED
@@ -17,7 +17,8 @@ module EventMachine
17
17
  #
18
18
  class Queue
19
19
  def initialize
20
- @items = []
20
+ @sink = []
21
+ @drain = []
21
22
  @popq = []
22
23
  end
23
24
 
@@ -29,10 +30,14 @@ module EventMachine
29
30
  def pop(*a, &b)
30
31
  cb = EM::Callback(*a, &b)
31
32
  EM.schedule do
32
- if @items.empty?
33
+ if @drain.empty?
34
+ @drain = @sink
35
+ @sink = []
36
+ end
37
+ if @drain.empty?
33
38
  @popq << cb
34
39
  else
35
- cb.call @items.shift
40
+ cb.call @drain.shift
36
41
  end
37
42
  end
38
43
  nil # Always returns nil
@@ -43,8 +48,12 @@ module EventMachine
43
48
  # next reactor tick.
44
49
  def push(*items)
45
50
  EM.schedule do
46
- @items.push(*items)
47
- @popq.shift.call @items.shift until @items.empty? || @popq.empty?
51
+ @sink.push(*items)
52
+ unless @popq.empty?
53
+ @drain = @sink
54
+ @sink = []
55
+ @popq.shift.call @drain.shift until @drain.empty? || @popq.empty?
56
+ end
48
57
  end
49
58
  end
50
59
  alias :<< :push
@@ -52,13 +61,13 @@ module EventMachine
52
61
  # @return [Boolean]
53
62
  # @note This is a peek, it's not thread safe, and may only tend toward accuracy.
54
63
  def empty?
55
- @items.empty?
64
+ @drain.empty? && @sink.empty?
56
65
  end
57
66
 
58
67
  # @return [Integer] Queue size
59
68
  # @note This is a peek, it's not thread safe, and may only tend toward accuracy.
60
69
  def size
61
- @items.size
70
+ @drain.size + @sink.size
62
71
  end
63
72
 
64
73
  # @return [Integer] Waiting size
data/lib/em/resolver.rb CHANGED
@@ -2,30 +2,31 @@ module EventMachine
2
2
  module DNS
3
3
  class Resolver
4
4
 
5
+ def self.windows?
6
+ if RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
7
+ require 'win32/resolv'
8
+ true
9
+ else
10
+ false
11
+ end
12
+ end
13
+
14
+ HOSTS_FILE = windows? ? Win32::Resolv.get_hosts_path : '/etc/hosts'
15
+
16
+ @hosts = nil
17
+ @nameservers = nil
18
+ @socket = nil
19
+
5
20
  def self.resolve(hostname)
6
21
  Request.new(socket, hostname)
7
22
  end
8
23
 
9
- @socket = @nameservers = nil
10
-
11
24
  def self.socket
12
- if !@socket || (@socket && @socket.error?)
25
+ if @socket && @socket.error?
13
26
  @socket = Socket.open
14
-
15
- @hosts = {}
16
- IO.readlines('/etc/hosts').each do |line|
17
- next if line =~ /^#/
18
- addr, host = line.split(/\s+/)
19
-
20
- if @hosts[host]
21
- @hosts[host] << addr
22
- else
23
- @hosts[host] = [addr]
24
- end
25
- end
27
+ else
28
+ @socket ||= Socket.open
26
29
  end
27
-
28
- @socket
29
30
  end
30
31
 
31
32
  def self.nameservers=(ns)
@@ -33,15 +34,23 @@ module EventMachine
33
34
  end
34
35
 
35
36
  def self.nameservers
36
- if !@nameservers
37
- @nameservers = []
38
- IO.readlines('/etc/resolv.conf').each do |line|
39
- if line =~ /^nameserver (.+)$/
40
- @nameservers << $1.split(/\s+/).first
41
- end
37
+ return @nameservers if @nameservers
38
+
39
+ if windows?
40
+ _, ns = Win32::Resolv.get_resolv_info
41
+ return @nameservers = ns || []
42
+ end
43
+
44
+ @nameservers = []
45
+ IO.readlines('/etc/resolv.conf').each do |line|
46
+ if line =~ /^nameserver (.+)$/
47
+ @nameservers << $1.split(/\s+/).first
42
48
  end
43
49
  end
50
+
44
51
  @nameservers
52
+ rescue
53
+ @nameservers = []
45
54
  end
46
55
 
47
56
  def self.nameserver
@@ -49,7 +58,21 @@ module EventMachine
49
58
  end
50
59
 
51
60
  def self.hosts
61
+ return @hosts if @hosts
62
+
63
+ @hosts = {}
64
+ IO.readlines(HOSTS_FILE).each do |line|
65
+ next if line =~ /^#/
66
+ addr, host = line.split(/\s+/)
67
+
68
+ next unless addr && host
69
+ @hosts[host] ||= []
70
+ @hosts[host] << addr
71
+ end
72
+
52
73
  @hosts
74
+ rescue
75
+ @hosts = {}
53
76
  end
54
77
  end
55
78
 
@@ -71,7 +71,7 @@ module EventMachine
71
71
  begin
72
72
  result = yield @resource
73
73
  completion.succeed result
74
- rescue Exception => e
74
+ rescue => e
75
75
  completion.fail e
76
76
  end
77
77
  end
@@ -87,4 +87,4 @@ module EventMachine
87
87
  end
88
88
 
89
89
  end
90
- end
90
+ end
data/lib/em/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.9.1"
2
+ VERSION = "1.2.0.1"
3
3
  end
data/lib/eventmachine.rb CHANGED
@@ -161,6 +161,7 @@ module EventMachine
161
161
  # Clean up reactor state so a new reactor boots up in this child.
162
162
  stop_event_loop
163
163
  release_machine
164
+ cleanup_machine
164
165
  @reactor_running = false
165
166
  end
166
167
 
@@ -198,30 +199,8 @@ module EventMachine
198
199
  @tails.pop.call
199
200
  end
200
201
 
201
- begin
202
- release_machine
203
- ensure
204
- if @threadpool
205
- @threadpool.each { |t| t.exit }
206
- @threadpool.each do |t|
207
- next unless t.alive?
208
- begin
209
- # Thread#kill! does not exist on 1.9 or rbx, and raises
210
- # NotImplemented on jruby
211
- t.kill!
212
- rescue NoMethodError, NotImplementedError
213
- t.kill
214
- # XXX t.join here?
215
- end
216
- end
217
- @threadqueue = nil
218
- @resultqueue = nil
219
- @threadpool = nil
220
- @all_threads_spawned = false
221
- end
222
-
223
- @next_tick_queue = []
224
- end
202
+ release_machine
203
+ cleanup_machine
225
204
  @reactor_running = false
226
205
  @reactor_thread = nil
227
206
  end
@@ -266,13 +245,30 @@ module EventMachine
266
245
  # Original patch by Aman Gupta.
267
246
  #
268
247
  Kernel.fork do
269
- if self.reactor_running?
270
- self.stop_event_loop
271
- self.release_machine
248
+ if reactor_running?
249
+ stop_event_loop
250
+ release_machine
251
+ cleanup_machine
272
252
  @reactor_running = false
253
+ @reactor_thread = nil
273
254
  end
274
- self.run block
255
+ run block
256
+ end
257
+ end
258
+
259
+ # Clean up Ruby space following a release_machine
260
+ def self.cleanup_machine
261
+ if @threadpool && !@threadpool.empty?
262
+ # Tell the threads to stop
263
+ @threadpool.each { |t| t.exit }
264
+ # Join the threads or bump the stragglers one more time
265
+ @threadpool.each { |t| t.join 0.01 || t.exit }
275
266
  end
267
+ @threadpool = nil
268
+ @threadqueue = nil
269
+ @resultqueue = nil
270
+ @all_threads_spawned = false
271
+ @next_tick_queue = []
276
272
  end
277
273
 
278
274
  # Adds a block to call as the reactor is shutting down.
@@ -997,11 +993,14 @@ module EventMachine
997
993
  # EventMachine.defer is used for integrating blocking operations into EventMachine's control flow.
998
994
  # The action of {.defer} is to take the block specified in the first parameter (the "operation")
999
995
  # and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
1000
- # When the operation completes, it will pass the result computed by the block (if any)
1001
- # back to the EventMachine reactor. Then, EventMachine calls the block specified in the
1002
- # second parameter to {.defer} (the "callback"), as part of its normal event handling loop.
1003
- # The result computed by the operation block is passed as a parameter to the callback.
1004
- # You may omit the callback parameter if you don't need to execute any code after the operation completes.
996
+ # When the operation completes, it will pass the result computed by the block (if any) back to the
997
+ # EventMachine reactor. Then, EventMachine calls the block specified in the second parameter to
998
+ # {.defer} (the "callback"), as part of its normal event handling loop. The result computed by the
999
+ # operation block is passed as a parameter to the callback. You may omit the callback parameter if
1000
+ # you don't need to execute any code after the operation completes. If the operation raises an
1001
+ # unhandled exception, the exception will be passed to the third parameter to {.defer} (the
1002
+ # "errback"), as part of its normal event handling loop. If no errback is provided, the exception
1003
+ # will be allowed to blow through to the main thread immediately.
1005
1004
  #
1006
1005
  # ## Caveats ##
1007
1006
  #
@@ -1015,6 +1014,11 @@ module EventMachine
1015
1014
  # the number of threads in its pool, so if you do this enough times, your subsequent deferred
1016
1015
  # operations won't get a chance to run.
1017
1016
  #
1017
+ # The threads within the EventMachine's thread pool have abort_on_exception set to true. As a result,
1018
+ # if an unhandled exception is raised by the deferred operation and an errback is not provided, it
1019
+ # will blow through to the main thread immediately. If the main thread is within an indiscriminate
1020
+ # rescue block at that time, the exception could be handled improperly by the main thread.
1021
+ #
1018
1022
  # @example
1019
1023
  #
1020
1024
  # operation = proc {
@@ -1024,14 +1028,18 @@ module EventMachine
1024
1028
  # callback = proc {|result|
1025
1029
  # # do something with result here, such as send it back to a network client.
1026
1030
  # }
1031
+ # errback = proc {|error|
1032
+ # # do something with error here, such as re-raising or logging.
1033
+ # }
1027
1034
  #
1028
- # EventMachine.defer(operation, callback)
1035
+ # EventMachine.defer(operation, callback, errback)
1029
1036
  #
1030
1037
  # @param [#call] op An operation you want to offload to EventMachine thread pool
1031
1038
  # @param [#call] callback A callback that will be run on the event loop thread after `operation` finishes.
1039
+ # @param [#call] errback An errback that will be run on the event loop thread after `operation` raises an exception.
1032
1040
  #
1033
1041
  # @see EventMachine.threadpool_size
1034
- def self.defer op = nil, callback = nil, &blk
1042
+ def self.defer op = nil, callback = nil, errback = nil, &blk
1035
1043
  # OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
1036
1044
  # without syncing there.
1037
1045
  #
@@ -1048,7 +1056,7 @@ module EventMachine
1048
1056
  spawn_threadpool
1049
1057
  end
1050
1058
 
1051
- @threadqueue << [op||blk,callback]
1059
+ @threadqueue << [op||blk,callback,errback]
1052
1060
  end
1053
1061
 
1054
1062
 
@@ -1059,13 +1067,18 @@ module EventMachine
1059
1067
  Thread.current.abort_on_exception = true
1060
1068
  while true
1061
1069
  begin
1062
- op, cback = *@threadqueue.pop
1070
+ op, cback, eback = *@threadqueue.pop
1063
1071
  rescue ThreadError
1064
1072
  $stderr.puts $!.message
1065
1073
  break # Ruby 2.0 may fail at Queue.pop
1066
1074
  end
1067
- result = op.call
1068
- @resultqueue << [result, cback]
1075
+ begin
1076
+ result = op.call
1077
+ @resultqueue << [result, cback]
1078
+ rescue Exception => error
1079
+ raise error unless eback
1080
+ @resultqueue << [error, eback]
1081
+ end
1069
1082
  EventMachine.signal_loopbreak
1070
1083
  end
1071
1084
  end
@@ -1477,9 +1490,13 @@ module EventMachine
1477
1490
  rescue Errno::EBADF, IOError
1478
1491
  end
1479
1492
  end
1480
- rescue
1481
- @wrapped_exception = $!
1482
- stop
1493
+ rescue Exception => e
1494
+ if stopping?
1495
+ @wrapped_exception = $!
1496
+ stop
1497
+ else
1498
+ raise e
1499
+ end
1483
1500
  end
1484
1501
  elsif c = @acceptors.delete( conn_binding )
1485
1502
  # no-op
Binary file
data/rakelib/package.rake CHANGED
@@ -25,7 +25,7 @@ else
25
25
  def setup_cross_compilation(ext)
26
26
  unless RUBY_PLATFORM =~ /mswin|mingw/
27
27
  ext.cross_compile = true
28
- ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60']
28
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
29
29
  end
30
30
  end
31
31
  def hack_cross_compilation(ext)
@@ -96,3 +96,25 @@ def gem_cmd(action, name, *args)
96
96
  end
97
97
 
98
98
  Rake::Task[:clean].enhance [:clobber_package]
99
+
100
+ # DevKit task following the example of Luis Lavena's test-ruby-c-extension
101
+ task :devkit do
102
+ begin
103
+ require "devkit"
104
+ rescue LoadError => e
105
+ abort "Failed to activate RubyInstaller's DevKit required for compilation."
106
+ end
107
+ end
108
+
109
+ if RUBY_PLATFORM =~ /mingw|mswin/
110
+ Rake::Task['compile'].prerequisites.unshift 'devkit'
111
+ end
112
+
113
+ desc "Build binary gems for Windows with rake-compiler-dock"
114
+ task 'gem:windows' do
115
+ require 'rake_compiler_dock'
116
+ RakeCompilerDock.sh <<-EOT
117
+ RUBY_CC_VERSION="${RUBY_CC_VERSION//1.8.7/}"
118
+ bundle && rake cross native gem
119
+ EOT
120
+ end
data/tests/dhparam.pem ADDED
@@ -0,0 +1,13 @@
1
+ -----BEGIN DH PARAMETERS-----
2
+ MIICCAKCAgEAikiatXa5aAteOtd6hOO33npjCvJByD3dwuM8rWzz0DFZdUH9nFJi
3
+ b0VvTVweVECb6XZBsrDNLqGQykCrm43swSk5D9XQCGJLxFERD6yk3b90xaeCm3/a
4
+ b0Ek5ZVvV73Cc/YbVmpBiOHoTFpUFJLZ7pLMQUSn8y3qUlNcY9/88HuwFi1s1lRM
5
+ ovihSRyZMYAuYWOD4yuOuIcroKVjD6gWFrsW9XrALWny6vUXQrhk8Q3rj+wM6ZtE
6
+ 5afcB0b6ZJtphrDfk3dFjOVG/zVT37VWgrY8GABrpo2ey0W0WIQJ7rDKLaPaI4kc
7
+ voOgC2K8Z3kSARZK+jULnwmBeYECz4EH/FF6FEp3GOKtkL4mqEkvh1n5EAesDOGl
8
+ iiX+RZXcUrZliSeifSXBTMJWWFVC0fkGIMb9PTZfZHyAC54lpuxzVki0HIyQG9Fs
9
+ 41zBJ5e8eEoXXlfUYtduUC35YGy2IxSzYLAJE76rctAZSWghha9xLOCDFoLjMr8h
10
+ FosKeHKJcBQ0bc8ymOpRIfrYLWhc0Pz2zkpJ/4eYw9t7NYg7S+jP19IE0gUnuM9v
11
+ SpoYMtS28tP9nEdokdwuBKD0D3bJEBBefDlHgfXoMgvy9Hivc9PBGGNTNpyFPpwF
12
+ sWVAkfhoNMJMC5V7LZsze+lftiDtzVoLSPDa9bO4BK7b/MgwCxfOhGsCAQI=
13
+ -----END DH PARAMETERS-----
@@ -31,6 +31,61 @@ class Test::Unit::TestCase
31
31
  @@port
32
32
  end
33
33
 
34
+ # Returns true if the host have a localhost 127.0.0.1 IPv4.
35
+ def self.local_ipv4?
36
+ return @@has_local_ipv4 if defined?(@@has_local_ipv4)
37
+ begin
38
+ get_my_ipv4_address "127.0.0.1"
39
+ @@has_local_ipv4 = true
40
+ rescue
41
+ @@has_local_ipv4 = false
42
+ end
43
+ end
44
+
45
+ # Returns true if the host have a public IPv4 and stores it in
46
+ # @@public_ipv4.
47
+ def self.public_ipv4?
48
+ return @@has_public_ipv4 if defined?(@@has_public_ipv4)
49
+ begin
50
+ @@public_ipv4 = get_my_ipv4_address "1.2.3.4"
51
+ @@has_public_ipv4 = true
52
+ rescue
53
+ @@has_public_ipv4 = false
54
+ end
55
+ end
56
+
57
+ # Returns true if the host have a localhost ::1 IPv6.
58
+ def self.local_ipv6?
59
+ return @@has_local_ipv6 if defined?(@@has_local_ipv6)
60
+ begin
61
+ get_my_ipv6_address "::1"
62
+ @@has_local_ipv6 = true
63
+ rescue
64
+ @@has_local_ipv6 = false
65
+ end
66
+ end
67
+
68
+ # Returns true if the host have a public IPv6 and stores it in
69
+ # @@public_ipv6.
70
+ def self.public_ipv6?
71
+ return @@has_public_ipv6 if defined?(@@has_public_ipv6)
72
+ begin
73
+ @@public_ipv6 = get_my_ipv6_address "2001::1"
74
+ @@has_public_ipv6 = true
75
+ rescue
76
+ @@has_public_ipv6 = false
77
+ end
78
+ end
79
+
80
+ # Returns an array with the localhost addresses (IPv4 and/or IPv6).
81
+ def local_ips
82
+ return @@local_ips if defined?(@@local_ips)
83
+ @@local_ips = []
84
+ @@local_ips << "127.0.0.1" if self.class.local_ipv4?
85
+ @@local_ips << "::1" if self.class.local_ipv6?
86
+ @@local_ips
87
+ end
88
+
34
89
  def exception_class
35
90
  jruby? ? NativeException : RuntimeError
36
91
  end
@@ -69,4 +124,28 @@ class Test::Unit::TestCase
69
124
  $VERBOSE = backup
70
125
  end
71
126
  end
127
+
128
+
129
+ private
130
+
131
+ def self.get_my_ipv4_address ip
132
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
133
+ UDPSocket.open(Socket::AF_INET) do |s|
134
+ s.connect ip, 1
135
+ s.addr.last
136
+ end
137
+ ensure
138
+ Socket.do_not_reverse_lookup = orig
139
+ end
140
+
141
+ def self.get_my_ipv6_address ip
142
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
143
+ UDPSocket.open(Socket::AF_INET6) do |s|
144
+ s.connect ip, 1
145
+ s.addr.last
146
+ end
147
+ ensure
148
+ Socket.do_not_reverse_lookup = orig
149
+ end
150
+
72
151
  end