spring 0.0.3 → 0.0.4

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.
@@ -1,7 +1,6 @@
1
1
  require "rbconfig"
2
2
  require "socket"
3
3
  require "pty"
4
- require "io/console"
5
4
 
6
5
  require "spring/version"
7
6
  require "spring/sid"
@@ -16,6 +15,8 @@ class Spring
16
15
  "-e", "Spring::Server.boot"
17
16
  ]
18
17
 
18
+ FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO)
19
+
19
20
  def self.run(args)
20
21
  exit new.run(args)
21
22
  end
@@ -58,13 +59,6 @@ class Spring
58
59
  server.send_io client
59
60
  server.puts rails_env_for(args.first)
60
61
 
61
- status = server.read(1)
62
-
63
- server.close
64
- client.close
65
-
66
- return false unless status == "0"
67
-
68
62
  application.send_io STDOUT
69
63
  application.send_io STDERR
70
64
  application.send_io stdin_slave
@@ -76,13 +70,25 @@ class Spring
76
70
  application.write arg
77
71
  end
78
72
 
79
- # FIXME: receive exit status from server
80
- application.read
81
- true
73
+ pid = server.gets.chomp
74
+
75
+ # We must not close the client socket until we are sure that the application has
76
+ # received the FD. Otherwise the FD can end up getting closed while it's in the server
77
+ # socket buffer on OS X. This doesn't happen on Linux.
78
+ client.close
79
+
80
+ if pid.empty?
81
+ false
82
+ else
83
+ forward_signals(pid.to_i)
84
+ application.read # FIXME: receive exit status from server
85
+ true
86
+ end
82
87
  rescue Errno::ECONNRESET
83
88
  false
84
89
  ensure
85
90
  application.close if application
91
+ server.close if server
86
92
  end
87
93
 
88
94
  private
@@ -97,21 +103,24 @@ class Spring
97
103
  end
98
104
  end
99
105
 
100
- # FIXME: need to make special chars (e.g. arrow keys) work
101
106
  def stdin_slave
102
107
  master, slave = PTY.open
103
- master.raw!
104
108
 
105
- Thread.new {
106
- until STDIN.closed?
107
- # This makes special chars work, but has some weird side-effects that
108
- # I need to figure out.
109
- # master.write STDIN.getch
109
+ # Sadly I cannot find a way to achieve this without shelling out to stty, or
110
+ # using a C extension library. [Ruby does not have direct support for calling
111
+ # tcsetattr().] We don't want to use a C extension library so
112
+ # that spring can be used by Rails in the future.
113
+ system "stty -icanon -echo"
114
+ at_exit { system "stty sane" }
110
115
 
111
- master.write STDIN.read(1)
112
- end
113
- }
116
+ Thread.new { master.write STDIN.read(1) until STDIN.closed? }
114
117
 
115
118
  slave
116
119
  end
120
+
121
+ def forward_signals(pid)
122
+ (FORWARDED_SIGNALS & Signal.list.keys).each do |sig|
123
+ trap(sig) { Process.kill(sig, pid) }
124
+ end
125
+ end
117
126
  end
@@ -21,7 +21,9 @@ class Spring
21
21
 
22
22
  @stdout = IO.new(STDOUT.fileno)
23
23
  @stderr = IO.new(STDERR.fileno)
24
- @stdin = IO.new(STDIN.fileno)
24
+ @stdin = File.open('/dev/null', 'r')
25
+
26
+ STDIN.reopen(@stdin)
25
27
  end
26
28
 
27
29
  def start
@@ -46,17 +48,7 @@ class Spring
46
48
  def run
47
49
  loop do
48
50
  watch_application
49
-
50
- client = manager.recv_io(UNIXSocket)
51
-
52
- # Confirm that we have received the client socket. This is necessary on OS X
53
- # to prevent a timing error. The client needs to keep the FD that we are receiving
54
- # open until it has been received here. Unlike on Linux, it's not sufficient for
55
- # the FD to just be in the socket buffer, it has to actually get received at this
56
- # end before it can be closed by the client.
57
- manager.puts
58
-
59
- serve client
51
+ serve manager.recv_io(UNIXSocket)
60
52
  end
61
53
  end
62
54
 
@@ -77,7 +69,13 @@ class Spring
77
69
  ActionDispatch::Reloader.cleanup!
78
70
  ActionDispatch::Reloader.prepare!
79
71
 
80
- Process.wait(fork { command.call(args) })
72
+ pid = fork {
73
+ IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
74
+ command.call(args)
75
+ }
76
+
77
+ manager.puts pid
78
+ Process.wait pid
81
79
  end
82
80
  ensure
83
81
  client.puts
@@ -29,10 +29,7 @@ class Spring
29
29
  @pid
30
30
  end
31
31
 
32
- # The return value of this method indicates whether or not the application
33
- # successfully received the client. It might not successfully receive the
34
- # client if e.g. the application has an exception during initialization, causing
35
- # the application process to die.
32
+ # Returns the pid of the process running the command, or nil if the application process died.
36
33
  def run(client)
37
34
  @client = client
38
35
 
@@ -49,11 +46,11 @@ class Spring
49
46
  start
50
47
  child.send_io @client
51
48
  end
52
-
53
- child.gets
54
49
  end
50
+
51
+ child.gets.chomp.to_i # get the pid
55
52
  rescue Errno::ECONNRESET, Errno::EPIPE
56
- false
53
+ nil
57
54
  ensure
58
55
  @client.close
59
56
  @client = nil
@@ -3,6 +3,8 @@ require "spring/sid"
3
3
  require "fileutils"
4
4
 
5
5
  class Spring
6
+ IGNORE_SIGNALS = %w(INT QUIT)
7
+
6
8
  class Env
7
9
  attr_reader :root
8
10
 
@@ -18,9 +18,9 @@ class Spring
18
18
  end
19
19
 
20
20
  def boot
21
- # Ignore SIGINT, otherwise the user typing ^C on the command line
22
- # will kill the background server.
23
- trap("INT", "IGNORE")
21
+ # Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line
22
+ # will kill the server/application.
23
+ IGNORE_SIGNALS.each { |sig| trap(sig, "IGNORE") }
24
24
 
25
25
  set_exit_hook
26
26
  write_pidfile
@@ -33,11 +33,7 @@ class Spring
33
33
  app_client = client.recv_io
34
34
  rails_env = client.gets.chomp
35
35
 
36
- if @applications[rails_env].run(app_client)
37
- client.write "0"
38
- else
39
- client.write "1"
40
- end
36
+ client.puts @applications[rails_env].run(app_client)
41
37
  end
42
38
 
43
39
  def set_exit_hook
@@ -1,3 +1,3 @@
1
1
  class Spring
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spring
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-11 00:00:00.000000000 Z
12
+ date: 2013-01-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport