1
1
require "spring/boot"
2
2
require "set"
3
3
require "pty"
4
+ require "spring/impl/application"
4
5
5
6
module Spring
6
7
class Application
8
+ include ApplicationImpl
7
9
attr_reader :manager , :watcher , :spring_env , :original_env
8
10
9
11
def initialize ( manager , original_env )
@@ -114,31 +116,28 @@ def preload
114
116
end
115
117
end
116
118
117
- def eager_preload
118
- with_pty { preload }
119
- end
120
-
121
119
def run
122
120
state :running
123
- manager . puts
121
+ notify_manager_ready
124
122
125
123
loop do
126
124
IO . select [ manager , @interrupt . first ]
127
125
128
126
if terminating? || watcher_stale? || preload_failed?
129
127
exit
130
128
else
131
- serve manager . recv_io ( UNIXSocket )
129
+ serve IOWrapper . recv_io ( manager , UNIXSocket ) . to_io
132
130
end
133
131
end
134
132
end
135
133
136
134
def serve ( client )
135
+ child_started = [ false ]
137
136
log "got client"
138
137
manager . puts
139
138
140
- stdout , stderr , stdin = streams = 3 . times . map { client . recv_io }
141
- [ STDOUT , STDERR , STDIN ] . zip ( streams ) . each { | a , b | a . reopen ( b ) }
139
+ stdout , stderr , stdin = streams = receive_streams ( client )
140
+ reopen_streams ( streams )
142
141
143
142
preload unless preloaded?
144
143
@@ -153,7 +152,7 @@ def serve(client)
153
152
ActionDispatch ::Reloader . prepare!
154
153
end
155
154
156
- pid = fork {
155
+ fork_child ( client , streams , child_started ) {
157
156
IGNORE_SIGNALS . each { |sig | trap ( sig , "DEFAULT" ) }
158
157
trap ( "TERM" , "DEFAULT" )
159
158
@@ -180,26 +179,21 @@ def serve(client)
180
179
invoke_after_fork_callbacks
181
180
shush_backtraces
182
181
182
+ before_command
183
183
command . call
184
184
}
185
-
186
- disconnect_database
187
- reset_streams
188
-
189
- log "forked #{ pid } "
190
- manager . puts pid
191
-
192
- wait pid , streams , client
193
185
rescue Exception => e
186
+ Kernel . exit if exiting? && e . is_a? ( SystemExit )
187
+
194
188
log "exception: #{ e } "
195
- manager . puts unless pid
189
+ manager . puts unless child_started [ 0 ]
196
190
197
191
if streams && !e . is_a? ( SystemExit )
198
- print_exception ( stderr , e )
192
+ print_exception ( stderr || STDERR , e )
199
193
streams . each ( &:close )
200
194
end
201
195
202
- client . puts ( 1 ) if pid
196
+ client . puts ( 1 ) if child_started [ 0 ]
203
197
client . close
204
198
end
205
199
@@ -280,39 +274,6 @@ def print_exception(stream, error)
280
274
rest . each { |line | stream . puts ( "\t from #{ line } " ) }
281
275
end
282
276
283
- def with_pty
284
- PTY . open do |master , slave |
285
- [ STDOUT , STDERR , STDIN ] . each { |s | s . reopen slave }
286
- Thread . new { master . read }
287
- yield
288
- reset_streams
289
- end
290
- end
291
-
292
- def reset_streams
293
- [ STDOUT , STDERR ] . each { |stream | stream . reopen ( spring_env . log_file ) }
294
- STDIN . reopen ( "/dev/null" )
295
- end
296
-
297
- def wait ( pid , streams , client )
298
- @mutex . synchronize { @waiting << pid }
299
-
300
- # Wait in a separate thread so we can run multiple commands at once
301
- Thread . new {
302
- begin
303
- _ , status = Process . wait2 pid
304
- log "#{ pid } exited with #{ status . exitstatus } "
305
-
306
- streams . each ( &:close )
307
- client . puts ( status . exitstatus )
308
- client . close
309
- ensure
310
- @mutex . synchronize { @waiting . delete pid }
311
- exit_if_finished
312
- end
313
- }
314
- end
315
-
316
277
private
317
278
318
279
def active_record_configured?
0 commit comments