Skip to content

Commit

Permalink
Connect a PTY when preloading in background
Browse files Browse the repository at this point in the history
Readline + libedit gets messed up if it loads when not connected to a
terminal. This resolves that problem.

Fixes #244.
  • Loading branch information
jonleighton committed Feb 9, 2014
1 parent 250edaa commit 6e0a6e8
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Fix `$0` so that it is no longer prefixed with "spring ", as doing
this cause issues with rspec when running just `rspec` with no
arguments.
* Ensure we're always connected to a tty when preloading the
application in the background, in order to avoid loading issues
with readline + libedit which affected pry-rails.

## 1.1.0

Expand Down
24 changes: 20 additions & 4 deletions lib/spring/application.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "spring/boot"
require "set"
require "pty"

module Spring
class Application
Expand Down Expand Up @@ -108,6 +109,10 @@ def preload
end
end

def eager_preload
with_pty { preload }
end

def run
state :running
manager.puts
Expand All @@ -128,7 +133,7 @@ def serve(client)
manager.puts

stdout, stderr, stdin = streams = 3.times.map { client.recv_io }
[STDOUT, STDERR].zip([stdout, stderr]).each { |a, b| a.reopen(b) }
[STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }

preload unless preloaded?

Expand All @@ -144,8 +149,6 @@ def serve(client)
end

pid = fork {
Process.setsid
STDIN.reopen(stdin)
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
trap("TERM", "DEFAULT")

Expand All @@ -172,7 +175,7 @@ def serve(client)
}

disconnect_database
[STDOUT, STDERR].each { |stream| stream.reopen(spring_env.log_file) }
reset_streams

log "forked #{pid}"
manager.puts pid
Expand Down Expand Up @@ -273,5 +276,18 @@ def print_exception(stream, error)
stream.puts("#{first}: #{error} (#{error.class})")
rest.each { |line| stream.puts("\tfrom #{line}") }
end

def with_pty
PTY.open do |master, slave|
[STDOUT, STDERR, STDIN].each { |s| s.reopen slave }
yield
reset_streams
end
end

def reset_streams
[STDOUT, STDERR].each { |stream| stream.reopen(spring_env.log_file) }
STDIN.reopen("/dev/null")
end
end
end
6 changes: 4 additions & 2 deletions lib/spring/application/boot.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This is necessary for the terminal to work correctly when we reopen stdin.
Process.setsid

require "spring/application"

app = Spring::Application.new(
Expand All @@ -6,11 +9,10 @@
)

Signal.trap("TERM") { app.terminate }
Signal.trap("TTOU", "IGNORE")

Spring::ProcessTitleUpdater.run { |distance|
"spring app | #{app.app_name} | started #{distance} ago | #{app.app_env} mode"
}

app.preload if ENV.delete("SPRING_PRELOAD") == "1"
app.eager_preload if ENV.delete("SPRING_PRELOAD") == "1"
app.run

0 comments on commit 6e0a6e8

Please sign in to comment.