11require "spring/boot"
22require "set"
33require "pty"
4+ require "spring/impl/application"
45
56module Spring
67 class Application
8+ include ApplicationImpl
79 attr_reader :manager , :watcher , :spring_env , :original_env
810
911 def initialize ( manager , original_env )
@@ -114,31 +116,28 @@ def preload
114116 end
115117 end
116118
117- def eager_preload
118- with_pty { preload }
119- end
120-
121119 def run
122120 state :running
123- manager . puts
121+ notify_manager_ready
124122
125123 loop do
126124 IO . select [ manager , @interrupt . first ]
127125
128126 if terminating? || watcher_stale? || preload_failed?
129127 exit
130128 else
131- serve manager . recv_io ( UNIXSocket )
129+ serve IOWrapper . recv_io ( manager , UNIXSocket ) . to_io
132130 end
133131 end
134132 end
135133
136134 def serve ( client )
135+ child_started = [ false ]
137136 log "got client"
138137 manager . puts
139138
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 )
142141
143142 preload unless preloaded?
144143
@@ -153,7 +152,7 @@ def serve(client)
153152 ActionDispatch ::Reloader . prepare!
154153 end
155154
156- pid = fork {
155+ fork_child ( client , streams , child_started ) {
157156 IGNORE_SIGNALS . each { |sig | trap ( sig , "DEFAULT" ) }
158157 trap ( "TERM" , "DEFAULT" )
159158
@@ -180,26 +179,21 @@ def serve(client)
180179 invoke_after_fork_callbacks
181180 shush_backtraces
182181
182+ before_command
183183 command . call
184184 }
185-
186- disconnect_database
187- reset_streams
188-
189- log "forked #{ pid } "
190- manager . puts pid
191-
192- wait pid , streams , client
193185 rescue Exception => e
186+ Kernel . exit if exiting? && e . is_a? ( SystemExit )
187+
194188 log "exception: #{ e } "
195- manager . puts unless pid
189+ manager . puts unless child_started [ 0 ]
196190
197191 if streams && !e . is_a? ( SystemExit )
198- print_exception ( stderr , e )
192+ print_exception ( stderr || STDERR , e )
199193 streams . each ( &:close )
200194 end
201195
202- client . puts ( 1 ) if pid
196+ client . puts ( 1 ) if child_started [ 0 ]
203197 client . close
204198 end
205199
@@ -280,39 +274,6 @@ def print_exception(stream, error)
280274 rest . each { |line | stream . puts ( "\t from #{ line } " ) }
281275 end
282276
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-
316277 private
317278
318279 def active_record_configured?
0 commit comments