Class: Spring::Client::Run

Inherits:
Command
  • Object
show all
Defined in:
lib/spring/client/run.rb

Constant Summary collapse

FORWARDED_SIGNALS =
%w(INT QUIT USR1 USR2 INFO) & Signal.list.keys

Instance Attribute Summary

Attributes inherited from Command

#args, #env

Instance Method Summary collapse

Methods inherited from Command

call, #initialize

Constructor Details

This class inherits a constructor from Spring::Client::Command

Instance Method Details

#boot_serverObject



29
30
31
32
33
34
35
36
# File 'lib/spring/client/run.rb', line 29

def boot_server
  env.socket_path.unlink if env.socket_path.exist?
  fork {
    require "spring/server"
    Spring::Server.boot
  }
  sleep 0.1 until env.socket_path.exist?
end

#callObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/spring/client/run.rb', line 13

def call
  Spring.verify_environment!

  boot_server unless env.server_running?
  verify_server_version

  application, client = UNIXSocket.pair

  connect_to_application(client)
  run_command(client, application)
rescue Errno::ECONNRESET
  exit 1
ensure
  server.close if @server
end

#connect_to_application(client) ⇒ Object



51
52
53
54
55
# File 'lib/spring/client/run.rb', line 51

def connect_to_application(client)
  server.send_io client
  send_json server, "args" => args, "default_rails_env" => default_rails_env
  server.gets or raise CommandNotFound
end

#default_rails_envObject



104
105
106
# File 'lib/spring/client/run.rb', line 104

def default_rails_env
  ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
end

#forward_signal(sig, pid) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/spring/client/run.rb', line 88

def forward_signal(sig, pid)
  Process.kill(sig, -Process.getpgid(pid))
rescue Errno::ESRCH
  # If the application process is gone, then don't block the
  # signal on this process.
  trap(sig, 'DEFAULT')
  Process.kill(sig, Process.pid)
end

#forward_signals(pid) ⇒ Object



82
83
84
85
86
# File 'lib/spring/client/run.rb', line 82

def forward_signals(pid)
  FORWARDED_SIGNALS.each do |sig|
    trap(sig) { forward_signal sig, pid }
  end
end

#run_command(client, application) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/spring/client/run.rb', line 57

def run_command(client, application)
  application.send_io STDOUT
  application.send_io STDERR
  application.send_io STDIN

  send_json application, args

  pid = server.gets
  pid = pid.chomp if pid

  # We must not close the client socket until we are sure that the application has
  # received the FD. Otherwise the FD can end up getting closed while it's in the server
  # socket buffer on OS X. This doesn't happen on Linux.
  client.close

  if pid && !pid.empty?
    forward_signals(pid.to_i)
    exit application.read.to_i
  else
    exit 1
  end
ensure
  application.close
end

#send_json(socket, data) ⇒ Object



97
98
99
100
101
102
# File 'lib/spring/client/run.rb', line 97

def send_json(socket, data)
  data = JSON.dump(data)

  socket.puts  data.bytesize
  socket.write data
end

#serverObject



9
10
11
# File 'lib/spring/client/run.rb', line 9

def server
  @server ||= UNIXSocket.open(env.socket_name)
end

#verify_server_versionObject



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/spring/client/run.rb', line 38

def verify_server_version
  server_version = server.gets.chomp
  if server_version != env.version
    $stderr.puts <<-ERROR
There is a version mismatch beween the spring client and the server.
You should restart the server and make sure to use the same version.

CLIENT: #{env.version}, SERVER: #{server_version}
ERROR
    exit 1
  end
end