eventmachine 1.0.3-x86-mingw32 → 1.2.0.dev.2-x86-mingw32
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +84 -1
- data/README.md +6 -7
- data/ext/binder.cpp +10 -10
- data/ext/binder.h +5 -5
- data/ext/cmain.cpp +173 -61
- data/ext/ed.cpp +262 -127
- data/ext/ed.h +50 -30
- data/ext/em.cpp +491 -445
- data/ext/em.h +101 -36
- data/ext/eventmachine.h +67 -51
- data/ext/extconf.rb +124 -31
- data/ext/fastfilereader/extconf.rb +9 -2
- data/ext/fastfilereader/mapper.cpp +3 -1
- data/ext/fastfilereader/rubymain.cpp +7 -7
- data/ext/kb.cpp +1 -1
- data/ext/pipe.cpp +11 -4
- data/ext/project.h +26 -6
- data/ext/rubymain.cpp +408 -201
- data/ext/ssl.cpp +167 -20
- data/ext/ssl.h +11 -2
- data/java/src/com/rubyeventmachine/EmReactor.java +16 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +2 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +6 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +55 -10
- data/lib/1.9/fastfilereaderext.so +0 -0
- data/lib/1.9/rubyeventmachine.so +0 -0
- data/lib/2.0/fastfilereaderext.so +0 -0
- data/lib/2.0/rubyeventmachine.so +0 -0
- data/lib/2.1/fastfilereaderext.so +0 -0
- data/lib/2.1/rubyeventmachine.so +0 -0
- data/lib/2.2/fastfilereaderext.so +0 -0
- data/lib/2.2/rubyeventmachine.so +0 -0
- data/lib/2.3/fastfilereaderext.so +0 -0
- data/lib/2.3/rubyeventmachine.so +0 -0
- data/lib/em/buftok.rb +34 -85
- data/lib/em/channel.rb +5 -0
- data/lib/em/completion.rb +2 -2
- data/lib/em/connection.rb +62 -4
- data/lib/em/iterator.rb +30 -48
- data/lib/em/pool.rb +1 -1
- data/lib/em/protocols/httpclient.rb +31 -11
- data/lib/em/protocols/line_and_text.rb +4 -4
- data/lib/em/protocols/linetext2.rb +44 -39
- data/lib/em/protocols/smtpclient.rb +60 -31
- data/lib/em/protocols/smtpserver.rb +32 -9
- data/lib/em/pure_ruby.rb +8 -3
- data/lib/em/queue.rb +16 -7
- data/lib/em/resolver.rb +64 -24
- data/lib/em/threaded_resource.rb +2 -2
- data/lib/em/tick_loop.rb +19 -19
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +96 -49
- data/lib/jeventmachine.rb +17 -0
- data/rakelib/package.rake +31 -4
- data/tests/dhparam.pem +13 -0
- data/tests/em_test_helper.rb +87 -0
- data/tests/test_attach.rb +25 -0
- data/tests/test_basic.rb +27 -38
- data/tests/test_channel.rb +14 -1
- data/tests/test_completion.rb +1 -0
- data/tests/test_connection_count.rb +22 -1
- data/tests/test_connection_write.rb +35 -0
- data/tests/test_defer.rb +17 -0
- data/tests/test_epoll.rb +26 -14
- data/tests/test_file_watch.rb +1 -0
- data/tests/test_fork.rb +75 -0
- data/tests/test_httpclient.rb +43 -0
- data/tests/test_idle_connection.rb +6 -4
- data/tests/test_ipv4.rb +125 -0
- data/tests/test_ipv6.rb +131 -0
- data/tests/test_iterator.rb +115 -0
- data/tests/test_kb.rb +19 -25
- data/tests/test_ltp2.rb +20 -0
- data/tests/test_many_fds.rb +22 -0
- data/tests/test_pause.rb +29 -0
- data/tests/test_pool.rb +2 -0
- data/tests/test_process_watch.rb +2 -0
- data/tests/test_processes.rb +7 -7
- data/tests/test_queue.rb +14 -0
- data/tests/test_resolver.rb +56 -7
- data/tests/test_set_sock_opt.rb +2 -0
- data/tests/test_smtpclient.rb +20 -0
- data/tests/test_ssl_args.rb +2 -2
- data/tests/test_ssl_dhparam.rb +83 -0
- data/tests/test_ssl_ecdh_curve.rb +79 -0
- data/tests/test_ssl_extensions.rb +49 -0
- data/tests/test_ssl_methods.rb +22 -5
- data/tests/test_ssl_protocols.rb +246 -0
- data/tests/test_ssl_verify.rb +103 -59
- data/tests/test_system.rb +4 -0
- data/tests/test_threaded_resource.rb +8 -0
- data/tests/test_unbind_reason.rb +5 -1
- metadata +173 -107
- data/.gitignore +0 -21
- data/.travis.yml +0 -12
- data/.yardopts +0 -7
- data/Gemfile +0 -2
- data/Rakefile +0 -20
- data/eventmachine.gemspec +0 -36
- data/rakelib/cpp.rake_example +0 -77
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
|
25
|
+
if @socket && @socket.error?
|
13
26
|
@socket = Socket.open
|
14
|
-
|
15
|
-
@
|
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
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
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
|
data/lib/em/threaded_resource.rb
CHANGED
data/lib/em/tick_loop.rb
CHANGED
@@ -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
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
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
|
|
data/lib/em/version.rb
CHANGED
data/lib/eventmachine.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
194
|
-
|
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
|
262
|
-
|
263
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
977
|
-
#
|
978
|
-
#
|
979
|
-
#
|
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
|
-
|
1037
|
-
|
1038
|
-
|
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
|
-
|
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
|
-
|
1452
|
-
|
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
|
-
|
1562
|
+
if defined?(handler::EM_CONNECTION_CLASS)
|
1516
1563
|
handler::EM_CONNECTION_CLASS
|
1517
|
-
|
1564
|
+
else
|
1518
1565
|
handler::const_set(:EM_CONNECTION_CLASS, Class.new(klass) {include handler})
|
1519
1566
|
end
|
1520
1567
|
else
|