eventmachine 1.0.3-x86-mingw32 → 1.2.0.dev.2-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +84 -1
  3. data/README.md +6 -7
  4. data/ext/binder.cpp +10 -10
  5. data/ext/binder.h +5 -5
  6. data/ext/cmain.cpp +173 -61
  7. data/ext/ed.cpp +262 -127
  8. data/ext/ed.h +50 -30
  9. data/ext/em.cpp +491 -445
  10. data/ext/em.h +101 -36
  11. data/ext/eventmachine.h +67 -51
  12. data/ext/extconf.rb +124 -31
  13. data/ext/fastfilereader/extconf.rb +9 -2
  14. data/ext/fastfilereader/mapper.cpp +3 -1
  15. data/ext/fastfilereader/rubymain.cpp +7 -7
  16. data/ext/kb.cpp +1 -1
  17. data/ext/pipe.cpp +11 -4
  18. data/ext/project.h +26 -6
  19. data/ext/rubymain.cpp +408 -201
  20. data/ext/ssl.cpp +167 -20
  21. data/ext/ssl.h +11 -2
  22. data/java/src/com/rubyeventmachine/EmReactor.java +16 -0
  23. data/java/src/com/rubyeventmachine/EventableChannel.java +2 -0
  24. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +6 -0
  25. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +55 -10
  26. data/lib/1.9/fastfilereaderext.so +0 -0
  27. data/lib/1.9/rubyeventmachine.so +0 -0
  28. data/lib/2.0/fastfilereaderext.so +0 -0
  29. data/lib/2.0/rubyeventmachine.so +0 -0
  30. data/lib/2.1/fastfilereaderext.so +0 -0
  31. data/lib/2.1/rubyeventmachine.so +0 -0
  32. data/lib/2.2/fastfilereaderext.so +0 -0
  33. data/lib/2.2/rubyeventmachine.so +0 -0
  34. data/lib/2.3/fastfilereaderext.so +0 -0
  35. data/lib/2.3/rubyeventmachine.so +0 -0
  36. data/lib/em/buftok.rb +34 -85
  37. data/lib/em/channel.rb +5 -0
  38. data/lib/em/completion.rb +2 -2
  39. data/lib/em/connection.rb +62 -4
  40. data/lib/em/iterator.rb +30 -48
  41. data/lib/em/pool.rb +1 -1
  42. data/lib/em/protocols/httpclient.rb +31 -11
  43. data/lib/em/protocols/line_and_text.rb +4 -4
  44. data/lib/em/protocols/linetext2.rb +44 -39
  45. data/lib/em/protocols/smtpclient.rb +60 -31
  46. data/lib/em/protocols/smtpserver.rb +32 -9
  47. data/lib/em/pure_ruby.rb +8 -3
  48. data/lib/em/queue.rb +16 -7
  49. data/lib/em/resolver.rb +64 -24
  50. data/lib/em/threaded_resource.rb +2 -2
  51. data/lib/em/tick_loop.rb +19 -19
  52. data/lib/em/version.rb +1 -1
  53. data/lib/eventmachine.rb +96 -49
  54. data/lib/jeventmachine.rb +17 -0
  55. data/rakelib/package.rake +31 -4
  56. data/tests/dhparam.pem +13 -0
  57. data/tests/em_test_helper.rb +87 -0
  58. data/tests/test_attach.rb +25 -0
  59. data/tests/test_basic.rb +27 -38
  60. data/tests/test_channel.rb +14 -1
  61. data/tests/test_completion.rb +1 -0
  62. data/tests/test_connection_count.rb +22 -1
  63. data/tests/test_connection_write.rb +35 -0
  64. data/tests/test_defer.rb +17 -0
  65. data/tests/test_epoll.rb +26 -14
  66. data/tests/test_file_watch.rb +1 -0
  67. data/tests/test_fork.rb +75 -0
  68. data/tests/test_httpclient.rb +43 -0
  69. data/tests/test_idle_connection.rb +6 -4
  70. data/tests/test_ipv4.rb +125 -0
  71. data/tests/test_ipv6.rb +131 -0
  72. data/tests/test_iterator.rb +115 -0
  73. data/tests/test_kb.rb +19 -25
  74. data/tests/test_ltp2.rb +20 -0
  75. data/tests/test_many_fds.rb +22 -0
  76. data/tests/test_pause.rb +29 -0
  77. data/tests/test_pool.rb +2 -0
  78. data/tests/test_process_watch.rb +2 -0
  79. data/tests/test_processes.rb +7 -7
  80. data/tests/test_queue.rb +14 -0
  81. data/tests/test_resolver.rb +56 -7
  82. data/tests/test_set_sock_opt.rb +2 -0
  83. data/tests/test_smtpclient.rb +20 -0
  84. data/tests/test_ssl_args.rb +2 -2
  85. data/tests/test_ssl_dhparam.rb +83 -0
  86. data/tests/test_ssl_ecdh_curve.rb +79 -0
  87. data/tests/test_ssl_extensions.rb +49 -0
  88. data/tests/test_ssl_methods.rb +22 -5
  89. data/tests/test_ssl_protocols.rb +246 -0
  90. data/tests/test_ssl_verify.rb +103 -59
  91. data/tests/test_system.rb +4 -0
  92. data/tests/test_threaded_resource.rb +8 -0
  93. data/tests/test_unbind_reason.rb +5 -1
  94. metadata +173 -107
  95. data/.gitignore +0 -21
  96. data/.travis.yml +0 -12
  97. data/.yardopts +0 -7
  98. data/Gemfile +0 -2
  99. data/Rakefile +0 -20
  100. data/eventmachine.gemspec +0 -36
  101. data/rakelib/cpp.rake_example +0 -77
@@ -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
 
@@ -66,7 +89,15 @@ module EventMachine
66
89
 
67
90
  def post_init
68
91
  @requests = {}
69
- EM.add_periodic_timer(0.1, &method(:tick))
92
+ end
93
+
94
+ def start_timer
95
+ @timer ||= EM.add_periodic_timer(0.1, &method(:tick))
96
+ end
97
+
98
+ def stop_timer
99
+ EM.cancel_timer(@timer)
100
+ @timer = nil
70
101
  end
71
102
 
72
103
  def unbind
@@ -84,6 +115,13 @@ module EventMachine
84
115
  else
85
116
  @requests[id] = req
86
117
  end
118
+
119
+ start_timer
120
+ end
121
+
122
+ def deregister_request(id, req)
123
+ @requests.delete(id)
124
+ stop_timer if @requests.length == 0
87
125
  end
88
126
 
89
127
  def send_packet(pkt)
@@ -109,6 +147,7 @@ module EventMachine
109
147
  req = @requests[msg.id]
110
148
  if req
111
149
  @requests.delete(msg.id)
150
+ stop_timer if @requests.length == 0
112
151
  req.receive_answer(msg)
113
152
  end
114
153
  end
@@ -140,6 +179,7 @@ module EventMachine
140
179
  if @tries < @max_tries
141
180
  send
142
181
  else
182
+ @socket.deregister_request(@id, self)
143
183
  fail 'retries exceeded'
144
184
  end
145
185
  end
@@ -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
@@ -7,25 +7,25 @@ module EventMachine
7
7
  # A TickLoop is useful when one needs to distribute amounts of work
8
8
  # throughout ticks in order to maintain response times. It is also useful for
9
9
  # simple repeated checks and metrics.
10
- #
11
- # # Here we run through an array one item per tick until it is empty,
12
- # # printing each element.
13
- # # When the array is empty, we return :stop from the callback, and the
14
- # # loop will terminate.
15
- # # When the loop terminates, the on_stop callbacks will be called.
16
- # EM.run do
17
- # array = (1..100).to_a
18
- #
19
- # tickloop = EM.tick_loop do
20
- # if array.empty?
21
- # :stop
22
- # else
23
- # puts array.shift
24
- # end
25
- # end
26
- #
27
- # tickloop.on_stop { EM.stop }
28
- # end
10
+ # @example
11
+ # # Here we run through an array one item per tick until it is empty,
12
+ # # printing each element.
13
+ # # When the array is empty, we return :stop from the callback, and the
14
+ # # loop will terminate.
15
+ # # When the loop terminates, the on_stop callbacks will be called.
16
+ # EM.run do
17
+ # array = (1..100).to_a
18
+ #
19
+ # tickloop = EM.tick_loop do
20
+ # if array.empty?
21
+ # :stop
22
+ # else
23
+ # puts array.shift
24
+ # end
25
+ # end
26
+ #
27
+ # tickloop.on_stop { EM.stop }
28
+ # end
29
29
  #
30
30
  class TickLoop
31
31
 
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.3"
2
+ VERSION = "1.2.0.dev.2"
3
3
  end
@@ -156,11 +156,12 @@ module EventMachine
156
156
  # will start without release_machine being called and will immediately throw
157
157
 
158
158
  #
159
- if reactor_running? and @reactor_pid != Process.pid
159
+ if @reactor_running and @reactor_pid != Process.pid
160
160
  # Reactor was started in a different parent, meaning we have forked.
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
 
@@ -184,36 +185,22 @@ module EventMachine
184
185
  add_timer(0) { signal_loopbreak }
185
186
  end
186
187
  @reactor_thread = Thread.current
187
- run_machine
188
+
189
+ # Rubinius needs to come back into "Ruby space" for GC to work,
190
+ # so we'll crank the machine here.
191
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
192
+ while run_machine_once; end
193
+ else
194
+ run_machine
195
+ end
196
+
188
197
  ensure
189
198
  until @tails.empty?
190
199
  @tails.pop.call
191
200
  end
192
201
 
193
- begin
194
- release_machine
195
- ensure
196
- if @threadpool
197
- @threadpool.each { |t| t.exit }
198
- @threadpool.each do |t|
199
- next unless t.alive?
200
- begin
201
- # Thread#kill! does not exist on 1.9 or rbx, and raises
202
- # NotImplemented on jruby
203
- t.kill!
204
- rescue NoMethodError, NotImplementedError
205
- t.kill
206
- # XXX t.join here?
207
- end
208
- end
209
- @threadqueue = nil
210
- @resultqueue = nil
211
- @threadpool = nil
212
- @all_threads_spawned = false
213
- end
214
-
215
- @next_tick_queue = []
216
- end
202
+ release_machine
203
+ cleanup_machine
217
204
  @reactor_running = false
218
205
  @reactor_thread = nil
219
206
  end
@@ -258,15 +245,32 @@ module EventMachine
258
245
  # Original patch by Aman Gupta.
259
246
  #
260
247
  Kernel.fork do
261
- if self.reactor_running?
262
- self.stop_event_loop
263
- self.release_machine
248
+ if reactor_running?
249
+ stop_event_loop
250
+ release_machine
251
+ cleanup_machine
264
252
  @reactor_running = false
253
+ @reactor_thread = nil
265
254
  end
266
- self.run block
255
+ run block
267
256
  end
268
257
  end
269
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 }
266
+ end
267
+ @threadpool = nil
268
+ @threadqueue = nil
269
+ @resultqueue = nil
270
+ @all_threads_spawned = false
271
+ @next_tick_queue = []
272
+ end
273
+
270
274
  # Adds a block to call as the reactor is shutting down.
271
275
  #
272
276
  # These callbacks are called in the _reverse_ order to which they are added.
@@ -531,6 +535,15 @@ module EventMachine
531
535
  s
532
536
  end
533
537
 
538
+ # Attach to an existing socket's file descriptor. The socket may have been
539
+ # started with {EventMachine.start_server}.
540
+ def self.attach_server sock, handler=nil, *args, &block
541
+ klass = klass_from_handler(Connection, handler, *args)
542
+ sd = sock.respond_to?(:fileno) ? sock.fileno : sock
543
+ s = attach_sd(sd)
544
+ @acceptors[s] = [klass,args,block,sock]
545
+ s
546
+ end
534
547
 
535
548
  # Stop a TCP server socket that was started with {EventMachine.start_server}.
536
549
  # @see EventMachine.start_server
@@ -737,7 +750,12 @@ module EventMachine
737
750
  end
738
751
 
739
752
  if io.respond_to?(:fileno)
740
- fd = defined?(JRuby) ? JRuby.runtime.getDescriptorByFileno(io.fileno).getChannel : io.fileno
753
+ # getDescriptorByFileno deprecated in JRuby 1.7.x, removed in JRuby 9000
754
+ if defined?(JRuby) && JRuby.runtime.respond_to?(:getDescriptorByFileno)
755
+ fd = JRuby.runtime.getDescriptorByFileno(io.fileno).getChannel
756
+ else
757
+ fd = io.fileno
758
+ end
741
759
  else
742
760
  fd = io
743
761
  end
@@ -957,13 +975,16 @@ module EventMachine
957
975
  callback = @next_tick_mutex.synchronize { @next_tick_queue.shift }
958
976
  begin
959
977
  callback.call
978
+ rescue
979
+ exception_raised = true
980
+ raise
960
981
  ensure
961
982
  # This is a little nasty. The problem is, if an exception occurs during
962
983
  # the callback, then we need to send a signal to the reactor to actually
963
984
  # do some work during the next_tick. The only mechanism we have from the
964
985
  # ruby side is next_tick itself, although ideally, we'd just drop a byte
965
986
  # on the loopback descriptor.
966
- EM.next_tick {} if $!
987
+ EM.next_tick {} if exception_raised
967
988
  end
968
989
  end
969
990
  end
@@ -972,11 +993,14 @@ module EventMachine
972
993
  # EventMachine.defer is used for integrating blocking operations into EventMachine's control flow.
973
994
  # The action of {.defer} is to take the block specified in the first parameter (the "operation")
974
995
  # and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
975
- # When the operation completes, it will pass the result computed by the block (if any)
976
- # back to the EventMachine reactor. Then, EventMachine calls the block specified in the
977
- # second parameter to {.defer} (the "callback"), as part of its normal event handling loop.
978
- # The result computed by the operation block is passed as a parameter to the callback.
979
- # 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.
980
1004
  #
981
1005
  # ## Caveats ##
982
1006
  #
@@ -990,6 +1014,11 @@ module EventMachine
990
1014
  # the number of threads in its pool, so if you do this enough times, your subsequent deferred
991
1015
  # operations won't get a chance to run.
992
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
+ #
993
1022
  # @example
994
1023
  #
995
1024
  # operation = proc {
@@ -999,14 +1028,18 @@ module EventMachine
999
1028
  # callback = proc {|result|
1000
1029
  # # do something with result here, such as send it back to a network client.
1001
1030
  # }
1031
+ # errback = proc {|error|
1032
+ # # do something with error here, such as re-raising or logging.
1033
+ # }
1002
1034
  #
1003
- # EventMachine.defer(operation, callback)
1035
+ # EventMachine.defer(operation, callback, errback)
1004
1036
  #
1005
1037
  # @param [#call] op An operation you want to offload to EventMachine thread pool
1006
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.
1007
1040
  #
1008
1041
  # @see EventMachine.threadpool_size
1009
- def self.defer op = nil, callback = nil, &blk
1042
+ def self.defer op = nil, callback = nil, errback = nil, &blk
1010
1043
  # OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
1011
1044
  # without syncing there.
1012
1045
  #
@@ -1023,7 +1056,7 @@ module EventMachine
1023
1056
  spawn_threadpool
1024
1057
  end
1025
1058
 
1026
- @threadqueue << [op||blk,callback]
1059
+ @threadqueue << [op||blk,callback,errback]
1027
1060
  end
1028
1061
 
1029
1062
 
@@ -1033,9 +1066,19 @@ module EventMachine
1033
1066
  thread = Thread.new do
1034
1067
  Thread.current.abort_on_exception = true
1035
1068
  while true
1036
- op, cback = *@threadqueue.pop
1037
- result = op.call
1038
- @resultqueue << [result, cback]
1069
+ begin
1070
+ op, cback, eback = *@threadqueue.pop
1071
+ rescue ThreadError
1072
+ $stderr.puts $!.message
1073
+ break # Ruby 2.0 may fail at Queue.pop
1074
+ end
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
1039
1082
  EventMachine.signal_loopbreak
1040
1083
  end
1041
1084
  end
@@ -1181,7 +1224,7 @@ module EventMachine
1181
1224
  #
1182
1225
  # @return [Boolean] true if the EventMachine reactor loop is currently running
1183
1226
  def self.reactor_running?
1184
- (@reactor_running || false)
1227
+ @reactor_running && Process.pid == @reactor_pid
1185
1228
  end
1186
1229
 
1187
1230
 
@@ -1447,9 +1490,13 @@ module EventMachine
1447
1490
  rescue Errno::EBADF, IOError
1448
1491
  end
1449
1492
  end
1450
- rescue
1451
- @wrapped_exception = $!
1452
- stop
1493
+ rescue Exception => e
1494
+ if stopping?
1495
+ @wrapped_exception = $!
1496
+ stop
1497
+ else
1498
+ raise e
1499
+ end
1453
1500
  end
1454
1501
  elsif c = @acceptors.delete( conn_binding )
1455
1502
  # no-op
@@ -1512,9 +1559,9 @@ module EventMachine
1512
1559
  raise ArgumentError, "must provide module or subclass of #{klass.name}" unless klass >= handler
1513
1560
  handler
1514
1561
  elsif handler
1515
- begin
1562
+ if defined?(handler::EM_CONNECTION_CLASS)
1516
1563
  handler::EM_CONNECTION_CLASS
1517
- rescue NameError
1564
+ else
1518
1565
  handler::const_set(:EM_CONNECTION_CLASS, Class.new(klass) {include handler})
1519
1566
  end
1520
1567
  else