eventmachine 1.0.9.1-java → 1.2.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
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