eventmachine-eventmachine 0.12.7 → 0.12.8
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.
- data/{docs/README → README} +21 -13
- data/Rakefile +14 -4
- data/docs/DEFERRABLES +0 -5
- data/docs/INSTALL +2 -4
- data/docs/LEGAL +1 -1
- data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
- data/docs/PURE_RUBY +0 -2
- data/docs/RELEASE_NOTES +0 -2
- data/docs/SMTP +0 -7
- data/docs/SPAWNED_PROCESSES +0 -4
- data/docs/TODO +0 -2
- data/eventmachine.gemspec +17 -8
- data/examples/ex_channel.rb +43 -0
- data/examples/ex_queue.rb +2 -0
- data/examples/helper.rb +2 -0
- data/ext/cmain.cpp +119 -20
- data/ext/cplusplus.cpp +15 -6
- data/ext/ed.cpp +303 -93
- data/ext/ed.h +49 -22
- data/ext/em.cpp +368 -42
- data/ext/em.h +43 -6
- data/ext/eventmachine.h +21 -8
- data/ext/eventmachine_cpp.h +1 -0
- data/ext/extconf.rb +4 -0
- data/ext/kb.cpp +1 -2
- data/ext/pipe.cpp +1 -3
- data/ext/project.h +21 -0
- data/ext/rubymain.cpp +232 -32
- data/ext/ssl.cpp +38 -1
- data/ext/ssl.h +5 -1
- data/java/src/com/rubyeventmachine/Application.java +7 -3
- data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
- data/lib/{protocols → em}/buftok.rb +16 -5
- data/lib/em/callback.rb +26 -0
- data/lib/em/channel.rb +57 -0
- data/lib/em/connection.rb +505 -0
- data/lib/em/deferrable.rb +144 -165
- data/lib/em/file_watch.rb +54 -0
- data/lib/em/future.rb +24 -25
- data/lib/em/messages.rb +1 -1
- data/lib/em/process_watch.rb +44 -0
- data/lib/em/processes.rb +58 -52
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +263 -0
- data/lib/em/protocols/httpclient2.rb +582 -0
- data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
- data/lib/em/protocols/linetext2.rb +160 -0
- data/lib/{protocols → em/protocols}/memcache.rb +37 -7
- data/lib/em/protocols/object_protocol.rb +39 -0
- data/lib/em/protocols/postgres3.rb +247 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +331 -0
- data/lib/em/protocols/smtpserver.rb +547 -0
- data/lib/em/protocols/stomp.rb +200 -0
- data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
- data/lib/em/protocols.rb +35 -0
- data/lib/em/queue.rb +61 -0
- data/lib/em/spawnable.rb +53 -56
- data/lib/em/streamer.rb +92 -74
- data/lib/em/timers.rb +55 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1008 -1298
- data/lib/evma.rb +1 -1
- data/lib/jeventmachine.rb +106 -101
- data/lib/pr_eventmachine.rb +47 -36
- data/tasks/project.rake +2 -1
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/test_attach.rb +18 -0
- data/tests/test_basic.rb +108 -54
- data/tests/test_channel.rb +63 -0
- data/tests/test_connection_count.rb +2 -2
- data/tests/test_epoll.rb +109 -110
- data/tests/test_errors.rb +36 -36
- data/tests/test_exc.rb +22 -25
- data/tests/test_file_watch.rb +49 -0
- data/tests/test_futures.rb +77 -93
- data/tests/test_hc.rb +2 -2
- data/tests/test_httpclient.rb +55 -52
- data/tests/test_httpclient2.rb +110 -112
- data/tests/test_inactivity_timeout.rb +30 -0
- data/tests/test_kb.rb +8 -9
- data/tests/test_ltp2.rb +274 -277
- data/tests/test_next_tick.rb +91 -65
- data/tests/test_object_protocol.rb +37 -0
- data/tests/test_process_watch.rb +48 -0
- data/tests/test_processes.rb +56 -23
- data/tests/test_proxy_connection.rb +92 -0
- data/tests/test_pure.rb +1 -5
- data/tests/test_queue.rb +44 -0
- data/tests/test_running.rb +9 -14
- data/tests/test_sasl.rb +32 -34
- data/tests/test_send_file.rb +175 -176
- data/tests/test_servers.rb +37 -41
- data/tests/test_smtpserver.rb +47 -55
- data/tests/test_spawn.rb +284 -291
- data/tests/test_ssl_args.rb +1 -1
- data/tests/test_ssl_methods.rb +1 -1
- data/tests/test_ssl_verify.rb +82 -0
- data/tests/test_timers.rb +81 -88
- data/tests/test_ud.rb +0 -7
- data/tests/testem.rb +1 -1
- metadata +53 -37
- data/lib/em/eventable.rb +0 -39
- data/lib/eventmachine_version.rb +0 -31
- data/lib/protocols/header_and_content.rb +0 -129
- data/lib/protocols/httpcli2.rb +0 -803
- data/lib/protocols/httpclient.rb +0 -270
- data/lib/protocols/linetext2.rb +0 -161
- data/lib/protocols/postgres.rb +0 -261
- data/lib/protocols/saslauth.rb +0 -179
- data/lib/protocols/smtpclient.rb +0 -308
- data/lib/protocols/smtpserver.rb +0 -556
- data/lib/protocols/stomp.rb +0 -153
- data/tests/test_eventables.rb +0 -77
data/lib/em/deferrable.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
#--
|
|
2
2
|
#
|
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
|
@@ -23,186 +23,165 @@
|
|
|
23
23
|
#
|
|
24
24
|
#
|
|
25
25
|
|
|
26
|
-
require 'forwardable'
|
|
27
|
-
|
|
28
26
|
module EventMachine
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
27
|
+
module Deferrable
|
|
28
|
+
|
|
29
|
+
# Specify a block to be executed if and when the Deferrable object receives
|
|
30
|
+
# a status of :succeeded. See #set_deferred_status for more information.
|
|
31
|
+
#
|
|
32
|
+
# Calling this method on a Deferrable object whose status is not yet known
|
|
33
|
+
# will cause the callback block to be stored on an internal list.
|
|
34
|
+
# If you call this method on a Deferrable whose status is :succeeded, the
|
|
35
|
+
# block will be executed immediately, receiving the parameters given to the
|
|
36
|
+
# prior #set_deferred_status call.
|
|
37
|
+
#
|
|
38
|
+
#--
|
|
39
|
+
# If there is no status, add a callback to an internal list.
|
|
40
|
+
# If status is succeeded, execute the callback immediately.
|
|
41
|
+
# If status is failed, do nothing.
|
|
42
|
+
#
|
|
43
|
+
def callback &block
|
|
44
|
+
return unless block
|
|
45
|
+
if @deferred_status == :succeeded
|
|
46
|
+
block.call(*@deferred_args)
|
|
47
|
+
elsif @deferred_status != :failed
|
|
48
|
+
@callbacks ||= []
|
|
49
|
+
@callbacks.unshift block # << block
|
|
50
|
+
end
|
|
53
51
|
end
|
|
54
|
-
end
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
# Specify a block to be executed if and when the Deferrable object receives
|
|
54
|
+
# a status of :failed. See #set_deferred_status for more information.
|
|
55
|
+
#--
|
|
56
|
+
# If there is no status, add an errback to an internal list.
|
|
57
|
+
# If status is failed, execute the errback immediately.
|
|
58
|
+
# If status is succeeded, do nothing.
|
|
59
|
+
#
|
|
60
|
+
def errback &block
|
|
61
|
+
return unless block
|
|
62
|
+
if @deferred_status == :failed
|
|
63
|
+
block.call(*@deferred_args)
|
|
64
|
+
elsif @deferred_status != :succeeded
|
|
65
|
+
@errbacks ||= []
|
|
66
|
+
@errbacks.unshift block # << block
|
|
67
|
+
end
|
|
70
68
|
end
|
|
71
|
-
end
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
70
|
+
# Sets the "disposition" (status) of the Deferrable object. See also the large set of
|
|
71
|
+
# sugarings for this method.
|
|
72
|
+
# Note that if you call this method without arguments,
|
|
73
|
+
# no arguments will be passed to the callback/errback.
|
|
74
|
+
# If the user has coded these with arguments, then the
|
|
75
|
+
# user code will throw an argument exception.
|
|
76
|
+
# Implementors of deferrable classes <b>must</b>
|
|
77
|
+
# document the arguments they will supply to user callbacks.
|
|
78
|
+
#
|
|
79
|
+
# OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
|
|
80
|
+
# on the INSIDE of a callback. This is very useful when a previously-registered
|
|
81
|
+
# callback wants to change the parameters that will be passed to subsequently-registered
|
|
82
|
+
# ones.
|
|
83
|
+
#
|
|
84
|
+
# You may give either :succeeded or :failed as the status argument.
|
|
85
|
+
#
|
|
86
|
+
# If you pass :succeeded, then all of the blocks passed to the object using the #callback
|
|
87
|
+
# method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
|
|
88
|
+
# passed to the object using #errback will be discarded.
|
|
89
|
+
#
|
|
90
|
+
# If you pass :failed, then all of the blocks passed to the object using the #errback
|
|
91
|
+
# method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
|
|
92
|
+
# passed to the object using # callback will be discarded.
|
|
93
|
+
#
|
|
94
|
+
# If you pass any arguments to #set_deferred_status in addition to the status argument,
|
|
95
|
+
# they will be passed as arguments to any callbacks or errbacks that are executed.
|
|
96
|
+
# It's your responsibility to ensure that the argument lists specified in your callbacks and
|
|
97
|
+
# errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
|
|
98
|
+
# an ArgumentError.
|
|
99
|
+
#
|
|
100
|
+
#--
|
|
101
|
+
# We're shifting callbacks off and discarding them as we execute them.
|
|
102
|
+
# This is valid because by definition callbacks are executed no more than
|
|
103
|
+
# once. It also has the magic effect of permitting recursive calls, which
|
|
104
|
+
# means that a callback can call #set_deferred_status and change the parameters
|
|
105
|
+
# that will be sent to subsequent callbacks down the chain.
|
|
106
|
+
#
|
|
107
|
+
# Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
|
|
108
|
+
# by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
|
|
109
|
+
# versions.
|
|
110
|
+
#
|
|
111
|
+
# Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
|
|
112
|
+
# handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
|
|
113
|
+
# which only allows status to be set once. Prior to making this change, it was possible
|
|
114
|
+
# to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
|
|
115
|
+
# triggering its errbacks! That is clearly undesirable, but it's just as undesirable
|
|
116
|
+
# to raise an exception is status is set more than once on a Deferrable. The latter
|
|
117
|
+
# behavior would invalidate the idiom of resetting arguments by setting status from
|
|
118
|
+
# within a callback or errback, but more seriously it would cause spurious errors
|
|
119
|
+
# if a Deferrable was timed out and then an attempt was made to succeed it. See the
|
|
120
|
+
# comments under the new method #timeout.
|
|
121
|
+
#
|
|
122
|
+
def set_deferred_status status, *args
|
|
123
|
+
cancel_timeout
|
|
124
|
+
@deferred_status = status
|
|
125
|
+
@deferred_args = args
|
|
126
|
+
case @deferred_status
|
|
127
|
+
when :succeeded
|
|
128
|
+
if @callbacks
|
|
129
|
+
while cb = @callbacks.pop
|
|
130
|
+
cb.call(*@deferred_args)
|
|
131
|
+
end
|
|
134
132
|
end
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
@errbacks.clear if @errbacks
|
|
134
|
+
when :failed
|
|
135
|
+
if @errbacks
|
|
136
|
+
while eb = @errbacks.pop
|
|
137
|
+
eb.call(*@deferred_args)
|
|
138
|
+
end
|
|
141
139
|
end
|
|
140
|
+
@callbacks.clear if @callbacks
|
|
142
141
|
end
|
|
143
|
-
@callbacks.clear if @callbacks
|
|
144
142
|
end
|
|
145
|
-
end
|
|
146
143
|
|
|
147
144
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
me = self
|
|
158
|
-
@deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
|
|
159
|
-
end
|
|
160
|
-
|
|
145
|
+
# Setting a timeout on a Deferrable causes it to go into the failed state after
|
|
146
|
+
# the Timeout expires (passing no arguments to the object's errbacks).
|
|
147
|
+
# Setting the status at any time prior to a call to the expiration of the timeout
|
|
148
|
+
# will cause the timer to be cancelled.
|
|
149
|
+
def timeout seconds
|
|
150
|
+
cancel_timeout
|
|
151
|
+
me = self
|
|
152
|
+
@deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
|
|
153
|
+
end
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
end
|
|
155
|
+
# Cancels an outstanding timeout if any. Undoes the action of #timeout.
|
|
156
|
+
#
|
|
157
|
+
def cancel_timeout
|
|
158
|
+
if @deferred_timeout
|
|
159
|
+
@deferred_timeout.cancel
|
|
160
|
+
@deferred_timeout = nil
|
|
161
|
+
end
|
|
162
|
+
end
|
|
171
163
|
|
|
172
164
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
165
|
+
# Sugar for set_deferred_status(:succeeded, ...)
|
|
166
|
+
#
|
|
167
|
+
def succeed *args
|
|
168
|
+
set_deferred_status :succeeded, *args
|
|
169
|
+
end
|
|
170
|
+
alias set_deferred_success succeed
|
|
178
171
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
172
|
+
# Sugar for set_deferred_status(:failed, ...)
|
|
173
|
+
#
|
|
174
|
+
def fail *args
|
|
175
|
+
set_deferred_status :failed, *args
|
|
176
|
+
end
|
|
177
|
+
alias set_deferred_failure fail
|
|
183
178
|
end
|
|
184
179
|
|
|
185
|
-
# And still more sugar
|
|
186
|
-
#
|
|
187
|
-
def succeed *args
|
|
188
|
-
set_deferred_success(*args)
|
|
189
|
-
end
|
|
190
180
|
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
|
|
181
|
+
# DefaultDeferrable is an otherwise empty class that includes Deferrable.
|
|
182
|
+
# This is very useful when you just need to return a Deferrable object
|
|
183
|
+
# as a way of communicating deferred status to some other part of a program.
|
|
184
|
+
class DefaultDeferrable
|
|
185
|
+
include Deferrable
|
|
195
186
|
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
# DefaultDeferrable is an otherwise empty class that includes Deferrable.
|
|
200
|
-
# This is very useful when you just need to return a Deferrable object
|
|
201
|
-
# as a way of communicating deferred status to some other part of a program.
|
|
202
|
-
#
|
|
203
|
-
class DefaultDeferrable
|
|
204
|
-
include Deferrable
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
end
|
|
208
|
-
|
|
187
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module EventMachine
|
|
2
|
+
|
|
3
|
+
# This is subclassed from EventMachine::Connection for use with the file monitoring API. Read the
|
|
4
|
+
# documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_file.
|
|
5
|
+
class FileWatch < Connection
|
|
6
|
+
# :stopdoc:
|
|
7
|
+
Cmodified = 'modified'.freeze
|
|
8
|
+
Cdeleted = 'deleted'.freeze
|
|
9
|
+
Cmoved = 'moved'.freeze
|
|
10
|
+
# :startdoc:
|
|
11
|
+
|
|
12
|
+
def receive_data(data) #:nodoc:
|
|
13
|
+
case data
|
|
14
|
+
when Cmodified
|
|
15
|
+
file_modified
|
|
16
|
+
when Cdeleted
|
|
17
|
+
file_deleted
|
|
18
|
+
when Cmoved
|
|
19
|
+
file_moved
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns the path that EventMachine::watch_file was originally called with. The current implementation
|
|
24
|
+
# does not pick up on the new filename after a rename occurs.
|
|
25
|
+
def path
|
|
26
|
+
@path
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Should be redefined with the user's custom callback that will be fired when the file is modified.
|
|
30
|
+
def file_modified
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Should be redefined with the user's custom callback that will be fired when the file is deleted.
|
|
34
|
+
# When the file is deleted, stop_watching will be called after this to make sure everything is
|
|
35
|
+
# cleaned up correctly.
|
|
36
|
+
#
|
|
37
|
+
# Note that on linux (with inotify), file_deleted will not be called until all open file descriptors to
|
|
38
|
+
# the file have been closed.
|
|
39
|
+
def file_deleted
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Should be redefined with the user's custom callback that will be fired when the file is moved or renamed.
|
|
43
|
+
def file_moved
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Discontinue monitoring of the file.
|
|
47
|
+
# This involves cleaning up the underlying monitoring details with kqueue/inotify, and in turn firing unbind.
|
|
48
|
+
# This will be called automatically when a file is deleted. User code may call it as well.
|
|
49
|
+
def stop_watching
|
|
50
|
+
EventMachine::unwatch_filename(@signature)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
data/lib/em/future.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
#--
|
|
2
2
|
#
|
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
|
@@ -23,39 +23,38 @@
|
|
|
23
23
|
#
|
|
24
24
|
#
|
|
25
25
|
|
|
26
|
+
#--
|
|
26
27
|
# This defines EventMachine::Deferrable#future, which requires
|
|
27
28
|
# that the rest of EventMachine::Deferrable has already been seen.
|
|
28
29
|
# (It's in deferrable.rb.)
|
|
29
|
-
#
|
|
30
|
-
# A future is a sugaring of a typical deferrable usage.
|
|
31
30
|
|
|
32
31
|
module EventMachine
|
|
33
32
|
module Deferrable
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
# A future is a sugaring of a typical deferrable usage.
|
|
35
|
+
#--
|
|
36
|
+
# Evaluate arg (which may be an expression or a block).
|
|
37
|
+
# What's the class of arg?
|
|
38
|
+
# If arg is an ordinary expression, then return it.
|
|
39
|
+
# If arg is deferrable (responds to :set_deferred_status),
|
|
40
|
+
# then look at the arguments. If either callback or errback
|
|
41
|
+
# are defined, then use them. If neither are defined, then
|
|
42
|
+
# use the supplied block (if any) as the callback.
|
|
43
|
+
# Then return arg.
|
|
44
|
+
def self.future arg, cb=nil, eb=nil, &blk
|
|
45
|
+
arg = arg.call if arg.respond_to?(:call)
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
if arg.respond_to?(:set_deferred_status)
|
|
48
|
+
if cb || eb
|
|
49
|
+
arg.callback(&cb) if cb
|
|
50
|
+
arg.errback(&eb) if eb
|
|
51
|
+
else
|
|
52
|
+
arg.callback(&blk) if blk
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
end
|
|
56
|
+
arg
|
|
57
|
+
end
|
|
59
58
|
|
|
60
59
|
end
|
|
61
60
|
end
|
data/lib/em/messages.rb
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module EventMachine
|
|
2
|
+
|
|
3
|
+
# This is subclassed from EventMachine::Connection for use with the process monitoring API. Read the
|
|
4
|
+
# documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_process.
|
|
5
|
+
class ProcessWatch < Connection
|
|
6
|
+
# :stopdoc:
|
|
7
|
+
Cfork = 'fork'.freeze
|
|
8
|
+
Cexit = 'exit'.freeze
|
|
9
|
+
# :startdoc:
|
|
10
|
+
|
|
11
|
+
def receive_data(data) # :nodoc:
|
|
12
|
+
case data
|
|
13
|
+
when Cfork
|
|
14
|
+
process_forked
|
|
15
|
+
when Cexit
|
|
16
|
+
process_exited
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the pid that EventMachine::watch_process was originally called with.
|
|
21
|
+
def pid
|
|
22
|
+
@pid
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Should be redefined with the user's custom callback that will be fired when the prcess is forked.
|
|
26
|
+
#
|
|
27
|
+
# There is currently not an easy way to get the pid of the forked child.
|
|
28
|
+
def process_forked
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Should be redefined with the user's custom callback that will be fired when the process exits.
|
|
32
|
+
#
|
|
33
|
+
# stop_watching is called automatically after this callback
|
|
34
|
+
def process_exited
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Discontinue monitoring of the process.
|
|
38
|
+
# This will be called automatically when a process dies. User code may call it as well.
|
|
39
|
+
def stop_watching
|
|
40
|
+
EventMachine::unwatch_pid(@signature)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
data/lib/em/processes.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
#--
|
|
2
2
|
#
|
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
|
@@ -26,43 +26,48 @@
|
|
|
26
26
|
|
|
27
27
|
module EventMachine
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
# EM::DeferrableChildProcess is a sugaring of a common use-case
|
|
30
|
+
# involving EM::popen.
|
|
31
|
+
# Call the #open method on EM::DeferrableChildProcess, passing
|
|
32
|
+
# a command-string. #open immediately returns an EM::Deferrable
|
|
33
|
+
# object. It also schedules the forking of a child process, which
|
|
34
|
+
# will execute the command passed to #open.
|
|
35
|
+
# When the forked child terminates, the Deferrable will be signalled
|
|
36
|
+
# and execute its callbacks, passing the data that the child process
|
|
37
|
+
# wrote to stdout.
|
|
38
|
+
#
|
|
39
|
+
class DeferrableChildProcess < EventMachine::Connection
|
|
40
|
+
include EventMachine::Deferrable
|
|
41
|
+
|
|
42
|
+
def initialize # :nodoc:
|
|
43
|
+
super
|
|
44
|
+
@data = []
|
|
45
|
+
end
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
# Sugars a common use-case involving forked child processes.
|
|
48
|
+
# #open takes a String argument containing an shell command
|
|
49
|
+
# string (including arguments if desired). #open immediately
|
|
50
|
+
# returns an EventMachine::Deferrable object, without blocking.
|
|
51
|
+
#
|
|
52
|
+
# It also invokes EventMachine#popen to run the passed-in
|
|
53
|
+
# command in a forked child process.
|
|
54
|
+
#
|
|
55
|
+
# When the forked child terminates, the Deferrable that
|
|
56
|
+
# #open calls its callbacks, passing the data returned
|
|
57
|
+
# from the child process.
|
|
58
|
+
#
|
|
59
|
+
def self.open cmd
|
|
60
|
+
EventMachine.popen( cmd, DeferrableChildProcess )
|
|
61
|
+
end
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
def receive_data data # :nodoc:
|
|
64
|
+
@data << data
|
|
65
|
+
end
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
def unbind # :nodoc:
|
|
68
|
+
succeed( @data.join )
|
|
69
|
+
end
|
|
70
|
+
end
|
|
66
71
|
|
|
67
72
|
class SystemCmd < EventMachine::Connection # :nodoc:
|
|
68
73
|
def initialize cb
|
|
@@ -83,31 +88,32 @@ module EventMachine
|
|
|
83
88
|
# The block or proc passed to EM::system is called with two arguments: the output generated by the command,
|
|
84
89
|
# and a Process::Status that contains information about the command's execution.
|
|
85
90
|
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
91
|
+
# EM.run{
|
|
92
|
+
# EM.system('ls'){ |output,status| puts output if status.exitstatus == 0 }
|
|
93
|
+
# }
|
|
89
94
|
#
|
|
90
95
|
# You can also supply an additional proc to send some data to the process:
|
|
91
96
|
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
# Like EM::popen, EM::system currently does not work on windows.
|
|
97
|
+
# EM.run{
|
|
98
|
+
# EM.system('sh', proc{ |process|
|
|
99
|
+
# process.send_data("echo hello\n")
|
|
100
|
+
# process.send_data("exit\n")
|
|
101
|
+
# }, proc{ |out,status|
|
|
102
|
+
# puts(out)
|
|
103
|
+
# })
|
|
104
|
+
# }
|
|
102
105
|
#
|
|
106
|
+
# Like EventMachine.popen, EventMachine.system currently does not work on windows.
|
|
107
|
+
# It returns the pid of the spawned process.
|
|
103
108
|
def EventMachine::system cmd, *args, &cb
|
|
104
109
|
cb ||= args.pop if args.last.is_a? Proc
|
|
105
110
|
init = args.pop if args.last.is_a? Proc
|
|
106
111
|
|
|
107
|
-
|
|
112
|
+
# merge remaining arguments into the command
|
|
113
|
+
cmd = ([cmd] + args.map{|a|a.to_s.dump}).join(' ')
|
|
114
|
+
|
|
115
|
+
EM.get_subprocess_pid(EM.popen(cmd, SystemCmd, cb) do |c|
|
|
108
116
|
init[c] if init
|
|
109
|
-
end
|
|
117
|
+
end.signature)
|
|
110
118
|
end
|
|
111
119
|
end
|
|
112
|
-
|
|
113
|
-
|