spring 0.0.5 → 0.0.6
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.
- data/README.md +95 -55
- data/bin/spring +2 -3
- data/lib/spring/application.rb +7 -8
- data/lib/spring/application_manager.rb +12 -5
- data/lib/spring/application_watcher.rb +4 -1
- data/lib/spring/client.rb +31 -0
- data/lib/spring/client/binstub.rb +67 -0
- data/lib/spring/client/command.rb +18 -0
- data/lib/spring/client/help.rb +23 -0
- data/lib/spring/client/run.rb +101 -0
- data/lib/spring/client/stop.rb +11 -0
- data/lib/spring/commands.rb +84 -22
- data/lib/spring/configuration.rb +31 -0
- data/lib/spring/env.rb +43 -5
- data/lib/spring/errors.rb +33 -0
- data/lib/spring/server.rb +9 -2
- data/lib/spring/sid.rb +1 -1
- data/lib/spring/version.rb +2 -2
- data/test/acceptance/app_test.rb +80 -18
- data/test/apps/rails-3-2/.gitignore +3 -0
- data/test/apps/rails-3-2/Gemfile +1 -2
- data/test/helper.rb +0 -1
- data/test/unit/application_watcher_test.rb +15 -3
- data/test/unit/commands_test.rb +34 -0
- metadata +14 -3
- data/lib/spring.rb +0 -151
data/lib/spring/server.rb
CHANGED
@@ -3,7 +3,7 @@ require "socket"
|
|
3
3
|
require "spring/env"
|
4
4
|
require "spring/application_manager"
|
5
5
|
|
6
|
-
|
6
|
+
module Spring
|
7
7
|
class Server
|
8
8
|
def self.boot
|
9
9
|
new.boot
|
@@ -25,15 +25,20 @@ class Spring
|
|
25
25
|
set_exit_hook
|
26
26
|
write_pidfile
|
27
27
|
|
28
|
+
$0 = "spring server | #{env.app_name} | started #{Time.now}"
|
29
|
+
|
28
30
|
server = UNIXServer.open(env.socket_name)
|
29
31
|
loop { serve server.accept }
|
30
32
|
end
|
31
33
|
|
32
34
|
def serve(client)
|
35
|
+
client.puts env.version
|
33
36
|
app_client = client.recv_io
|
34
37
|
rails_env = client.gets.chomp
|
35
38
|
|
36
39
|
client.puts @applications[rails_env].run(app_client)
|
40
|
+
rescue SocketError => e
|
41
|
+
raise e unless client.eof?
|
37
42
|
end
|
38
43
|
|
39
44
|
def set_exit_hook
|
@@ -45,6 +50,8 @@ class Spring
|
|
45
50
|
[env.socket_path, env.pidfile_path].each do |path|
|
46
51
|
path.unlink if path.exist?
|
47
52
|
end
|
53
|
+
|
54
|
+
@applications.values.each(&:stop)
|
48
55
|
end
|
49
56
|
end
|
50
57
|
end
|
@@ -56,7 +63,7 @@ class Spring
|
|
56
63
|
@pidfile.fsync
|
57
64
|
else
|
58
65
|
STDERR.puts "#{file.path} is locked; it looks like a server is already running"
|
59
|
-
exit
|
66
|
+
exit 1
|
60
67
|
end
|
61
68
|
end
|
62
69
|
end
|
data/lib/spring/sid.rb
CHANGED
data/lib/spring/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.0.
|
1
|
+
module Spring
|
2
|
+
VERSION = "0.0.6"
|
3
3
|
end
|
data/test/acceptance/app_test.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'io/wait'
|
3
3
|
require "timeout"
|
4
|
+
require "spring/sid"
|
5
|
+
require "spring/env"
|
4
6
|
|
5
7
|
class AppTest < ActiveSupport::TestCase
|
6
|
-
BINFILE = File.expand_path('../bin/spring', TEST_ROOT)
|
7
|
-
|
8
8
|
def app_root
|
9
|
-
"#{TEST_ROOT}/apps/rails-3-2"
|
9
|
+
Pathname.new("#{TEST_ROOT}/apps/rails-3-2")
|
10
10
|
end
|
11
11
|
|
12
12
|
def server_pidfile
|
13
13
|
"#{app_root}/tmp/spring/#{Spring::SID.sid}.pid"
|
14
14
|
end
|
15
15
|
|
16
|
+
def spring_env
|
17
|
+
@spring_env ||= Spring::Env.new(app_root)
|
18
|
+
end
|
19
|
+
|
16
20
|
def server_pid
|
17
|
-
|
21
|
+
spring_env.pid
|
22
|
+
end
|
23
|
+
|
24
|
+
def server_running?
|
25
|
+
spring_env.server_running?
|
18
26
|
end
|
19
27
|
|
20
28
|
def stdout
|
@@ -30,10 +38,15 @@ class AppTest < ActiveSupport::TestCase
|
|
30
38
|
|
31
39
|
Bundler.with_clean_env do
|
32
40
|
Process.spawn(
|
41
|
+
{
|
42
|
+
"GEM_HOME" => "#{app_root}/vendor/gems",
|
43
|
+
"GEM_PATH" => "",
|
44
|
+
"PATH" => "#{app_root}/vendor/gems/bin:#{ENV["PATH"]}"
|
45
|
+
},
|
33
46
|
command,
|
34
47
|
out: stdout.last,
|
35
48
|
err: stderr.last,
|
36
|
-
chdir: app_root,
|
49
|
+
chdir: app_root.to_s,
|
37
50
|
)
|
38
51
|
end
|
39
52
|
|
@@ -41,7 +54,9 @@ class AppTest < ActiveSupport::TestCase
|
|
41
54
|
|
42
55
|
out, err = read_streams
|
43
56
|
|
44
|
-
@times << (Time.now - start_time) if
|
57
|
+
@times << (Time.now - start_time) if @times
|
58
|
+
|
59
|
+
print_streams(out, err) if ENV["SPRING_DEBUG"]
|
45
60
|
|
46
61
|
[status, out, err]
|
47
62
|
rescue Timeout::Error
|
@@ -62,17 +77,17 @@ class AppTest < ActiveSupport::TestCase
|
|
62
77
|
end
|
63
78
|
|
64
79
|
def await_reload
|
65
|
-
sleep 0.
|
80
|
+
sleep 0.4
|
66
81
|
end
|
67
82
|
|
68
83
|
def assert_successful_run(*args)
|
69
84
|
status, _, _ = app_run(*args)
|
70
|
-
assert status.success?,
|
85
|
+
assert status.success?, "The run should be successful but it wasn't"
|
71
86
|
end
|
72
87
|
|
73
88
|
def assert_unsuccessful_run(*args)
|
74
89
|
status, _, _ = app_run(*args)
|
75
|
-
assert !status.success?,
|
90
|
+
assert !status.success?, "The run should not be successful but it was"
|
76
91
|
end
|
77
92
|
|
78
93
|
def assert_stdout(command, expected)
|
@@ -80,6 +95,11 @@ class AppTest < ActiveSupport::TestCase
|
|
80
95
|
assert stdout.include?(expected), "expected '#{expected}' to be printed to stdout. But it wasn't, the stdout is:\n#{stdout}"
|
81
96
|
end
|
82
97
|
|
98
|
+
def assert_stderr(command, expected)
|
99
|
+
_, _, stderr = app_run(command)
|
100
|
+
assert stderr.include?(expected), "expected '#{expected}' to be printed to stderr. But it wasn't, the stderr is:\n#{stderr}"
|
101
|
+
end
|
102
|
+
|
83
103
|
def assert_speedup(opts = {})
|
84
104
|
ratio = opts.fetch(:ratio, 0.5)
|
85
105
|
from = opts.fetch(:from, 0)
|
@@ -89,20 +109,40 @@ class AppTest < ActiveSupport::TestCase
|
|
89
109
|
assert (second / first) < ratio, "#{second} was not less than #{ratio} of #{first}"
|
90
110
|
end
|
91
111
|
|
112
|
+
def assert_server_running(*args)
|
113
|
+
assert server_running?, "The server should be running but it isn't"
|
114
|
+
end
|
115
|
+
|
116
|
+
def assert_server_not_running(*args)
|
117
|
+
assert !server_running?, "The server should not be running but it is"
|
118
|
+
end
|
119
|
+
|
92
120
|
def test_command
|
93
|
-
"
|
121
|
+
"spring test #{@test}"
|
94
122
|
end
|
95
123
|
|
124
|
+
@@installed_spring = false
|
125
|
+
|
96
126
|
setup do
|
97
127
|
@test = "#{app_root}/test/functional/posts_controller_test.rb"
|
98
128
|
@test_contents = File.read(@test)
|
99
129
|
@controller = "#{app_root}/app/controllers/posts_controller.rb"
|
100
130
|
@controller_contents = File.read(@controller)
|
101
131
|
|
102
|
-
@
|
132
|
+
@spring_env = Spring::Env.new(app_root)
|
133
|
+
|
134
|
+
unless @@installed_spring
|
135
|
+
system "gem build spring.gemspec 2>/dev/null 1>/dev/null"
|
136
|
+
app_run "gem install ../../../spring-*.gem"
|
137
|
+
@@installed_spring = true
|
138
|
+
end
|
139
|
+
|
140
|
+
FileUtils.rm_rf "#{app_root}/bin"
|
141
|
+
app_run "(gem list bundler | grep bundler) || gem install bundler", timeout: nil
|
142
|
+
app_run "bundle check || bundle update", timeout: nil
|
143
|
+
app_run "bundle exec rake db:migrate"
|
103
144
|
|
104
|
-
|
105
|
-
app_run "bundle exec rake db:migrate", timer: false
|
145
|
+
@times = []
|
106
146
|
end
|
107
147
|
|
108
148
|
teardown do
|
@@ -123,7 +163,7 @@ class AppTest < ActiveSupport::TestCase
|
|
123
163
|
end
|
124
164
|
|
125
165
|
test "help message when called without arguments" do
|
126
|
-
assert_stdout
|
166
|
+
assert_stdout "spring", 'Usage: spring COMMAND [ARGS]'
|
127
167
|
end
|
128
168
|
|
129
169
|
test "test changes are picked up" do
|
@@ -176,8 +216,7 @@ class AppTest < ActiveSupport::TestCase
|
|
176
216
|
CODE
|
177
217
|
File.write(@test, @test_contents.sub("get :index", "Foo.omg"))
|
178
218
|
|
179
|
-
|
180
|
-
2.times { await_reload }
|
219
|
+
await_reload
|
181
220
|
|
182
221
|
assert_stdout test_command, "RuntimeError: omg"
|
183
222
|
assert_stdout test_command, "RuntimeError: omg"
|
@@ -209,11 +248,34 @@ class AppTest < ActiveSupport::TestCase
|
|
209
248
|
end
|
210
249
|
end
|
211
250
|
|
251
|
+
test "stop command kills server" do
|
252
|
+
assert_successful_run test_command
|
253
|
+
assert_server_running
|
254
|
+
|
255
|
+
assert_successful_run 'spring stop'
|
256
|
+
assert_server_not_running
|
257
|
+
end
|
258
|
+
|
212
259
|
test "custom commands" do
|
213
|
-
assert_stdout "
|
260
|
+
assert_stdout "spring custom", "omg"
|
214
261
|
end
|
215
262
|
|
216
263
|
test "runner alias" do
|
217
|
-
assert_stdout "
|
264
|
+
assert_stdout "spring r 'puts 1'", "1"
|
265
|
+
end
|
266
|
+
|
267
|
+
test "binstubs" do
|
268
|
+
app_run "spring binstub rake"
|
269
|
+
assert_successful_run "bin/spring help"
|
270
|
+
assert_stdout "bin/rake -T", "rake db:migrate"
|
271
|
+
end
|
272
|
+
|
273
|
+
test "missing config/application.rb" do
|
274
|
+
begin
|
275
|
+
FileUtils.mv app_root.join("config/application.rb"), app_root.join("config/application.rb.bak")
|
276
|
+
assert_stderr "spring rake -T", "unable to find your config/application.rb"
|
277
|
+
ensure
|
278
|
+
FileUtils.mv app_root.join("config/application.rb.bak"), app_root.join("config/application.rb")
|
279
|
+
end
|
218
280
|
end
|
219
281
|
end
|
data/test/apps/rails-3-2/Gemfile
CHANGED
data/test/helper.rb
CHANGED
@@ -3,7 +3,7 @@ require "fileutils"
|
|
3
3
|
require "active_support/core_ext/numeric/time"
|
4
4
|
require "spring/application_watcher"
|
5
5
|
|
6
|
-
class ApplicationWatcherTest <
|
6
|
+
class ApplicationWatcherTest < ActiveSupport::TestCase
|
7
7
|
def setup
|
8
8
|
@dir = "/tmp/spring"
|
9
9
|
FileUtils.mkdir(@dir)
|
@@ -19,7 +19,7 @@ class ApplicationWatcherTest < Test::Unit::TestCase
|
|
19
19
|
FileUtils.touch(file, options)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
test "file mtime" do
|
23
23
|
file = "#{@dir}/omg"
|
24
24
|
touch file, Time.now - 2.seconds
|
25
25
|
|
@@ -31,7 +31,19 @@ class ApplicationWatcherTest < Test::Unit::TestCase
|
|
31
31
|
assert watcher.stale?
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
test "tolerates enoent" do
|
35
|
+
file = "#{@dir}/omg"
|
36
|
+
touch file
|
37
|
+
|
38
|
+
watcher = Spring::ApplicationWatcher.new
|
39
|
+
watcher.add_files [file]
|
40
|
+
|
41
|
+
assert !watcher.stale?
|
42
|
+
FileUtils.rm(file)
|
43
|
+
assert watcher.stale?
|
44
|
+
end
|
45
|
+
|
46
|
+
test "accepts glob patterns" do
|
35
47
|
FileUtils.mkdir("#{@dir}/1")
|
36
48
|
FileUtils.mkdir("#{@dir}/2")
|
37
49
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "helper"
|
2
|
+
require "spring/commands"
|
3
|
+
|
4
|
+
class CommandsTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
test "test command needs a test name" do
|
7
|
+
begin
|
8
|
+
real_stderr = $stderr
|
9
|
+
$stderr = StringIO.new('')
|
10
|
+
|
11
|
+
command = Spring::Commands::Test.new
|
12
|
+
command.call([])
|
13
|
+
|
14
|
+
assert_equal "you need to specify what test to run: spring test TEST_NAME\n", $stderr.string
|
15
|
+
ensure
|
16
|
+
$stderr = real_stderr
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
test "prints error message when preloaded file does not exist" do
|
21
|
+
begin
|
22
|
+
original_stderr = $stderr
|
23
|
+
$stderr = StringIO.new('')
|
24
|
+
my_command_class = Class.new(Spring::Commands::Command)
|
25
|
+
my_command_class.preloads = %w(i_do_not_exist)
|
26
|
+
|
27
|
+
my_command_class.new.setup
|
28
|
+
assert_match /The #<Class:0x[0-9a-f]+> command tried to preload i_do_not_exist but could not find it./, $stderr.string
|
29
|
+
ensure
|
30
|
+
$stderr = original_stderr
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
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.
|
4
|
+
version: 0.0.6
|
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-
|
12
|
+
date: 2013-02-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -58,12 +58,19 @@ files:
|
|
58
58
|
- README.md
|
59
59
|
- Rakefile
|
60
60
|
- bin/spring
|
61
|
-
- lib/spring.rb
|
62
61
|
- lib/spring/application.rb
|
63
62
|
- lib/spring/application_manager.rb
|
64
63
|
- lib/spring/application_watcher.rb
|
64
|
+
- lib/spring/client.rb
|
65
|
+
- lib/spring/client/binstub.rb
|
66
|
+
- lib/spring/client/command.rb
|
67
|
+
- lib/spring/client/help.rb
|
68
|
+
- lib/spring/client/run.rb
|
69
|
+
- lib/spring/client/stop.rb
|
65
70
|
- lib/spring/commands.rb
|
71
|
+
- lib/spring/configuration.rb
|
66
72
|
- lib/spring/env.rb
|
73
|
+
- lib/spring/errors.rb
|
67
74
|
- lib/spring/server.rb
|
68
75
|
- lib/spring/sid.rb
|
69
76
|
- lib/spring/version.rb
|
@@ -134,9 +141,11 @@ files:
|
|
134
141
|
- test/apps/rails-3-2/test/unit/post_test.rb
|
135
142
|
- test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep
|
136
143
|
- test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep
|
144
|
+
- test/apps/rails-3-2/vendor/gems/.gitkeep
|
137
145
|
- test/apps/rails-3-2/vendor/plugins/.gitkeep
|
138
146
|
- test/helper.rb
|
139
147
|
- test/unit/application_watcher_test.rb
|
148
|
+
- test/unit/commands_test.rb
|
140
149
|
homepage: http://github.com/jonleighton/spring
|
141
150
|
licenses: []
|
142
151
|
post_install_message:
|
@@ -228,6 +237,8 @@ test_files:
|
|
228
237
|
- test/apps/rails-3-2/test/unit/post_test.rb
|
229
238
|
- test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep
|
230
239
|
- test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep
|
240
|
+
- test/apps/rails-3-2/vendor/gems/.gitkeep
|
231
241
|
- test/apps/rails-3-2/vendor/plugins/.gitkeep
|
232
242
|
- test/helper.rb
|
233
243
|
- test/unit/application_watcher_test.rb
|
244
|
+
- test/unit/commands_test.rb
|
data/lib/spring.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
require "socket"
|
3
|
-
require "pty"
|
4
|
-
|
5
|
-
require "spring/version"
|
6
|
-
require "spring/sid"
|
7
|
-
require "spring/env"
|
8
|
-
require "spring/commands"
|
9
|
-
|
10
|
-
class Spring
|
11
|
-
SERVER_COMMAND = [
|
12
|
-
File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')),
|
13
|
-
"-I", File.expand_path("../", __FILE__),
|
14
|
-
"-r", "spring/server",
|
15
|
-
"-r", "bundler/setup",
|
16
|
-
"-e", "Spring::Server.boot"
|
17
|
-
]
|
18
|
-
|
19
|
-
FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO)
|
20
|
-
|
21
|
-
def self.run(args)
|
22
|
-
exit new.run(args)
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :env
|
26
|
-
|
27
|
-
def initialize
|
28
|
-
@env = Env.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def server_running?
|
32
|
-
if env.pidfile_path.exist?
|
33
|
-
pidfile = env.pidfile_path.open('r')
|
34
|
-
!pidfile.flock(File::LOCK_EX | File::LOCK_NB)
|
35
|
-
else
|
36
|
-
false
|
37
|
-
end
|
38
|
-
ensure
|
39
|
-
if pidfile
|
40
|
-
pidfile.flock(File::LOCK_UN)
|
41
|
-
pidfile.close
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Boot the server into the process group of the current session.
|
46
|
-
# This will cause it to be automatically killed once the session
|
47
|
-
# ends (i.e. when the user closes their terminal).
|
48
|
-
def boot_server
|
49
|
-
env.socket_path.unlink if env.socket_path.exist?
|
50
|
-
Process.spawn(*SERVER_COMMAND, pgroup: SID.pgid)
|
51
|
-
sleep 0.1 until env.socket_path.exist?
|
52
|
-
end
|
53
|
-
|
54
|
-
def run(args)
|
55
|
-
if self.class.command_registered?(args.first)
|
56
|
-
run_command(args)
|
57
|
-
else
|
58
|
-
print_help
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def print_help
|
65
|
-
puts <<-EOT
|
66
|
-
Usage: spring COMMAND [ARGS]
|
67
|
-
|
68
|
-
The most common spring commands are:
|
69
|
-
rake Run a rake task
|
70
|
-
console Start the Rails console
|
71
|
-
runner Execute a command with the Rails runner
|
72
|
-
generate Trigger a Rails generator
|
73
|
-
|
74
|
-
test Execute a Test::Unit test
|
75
|
-
rspec Execute an RSpec spec
|
76
|
-
EOT
|
77
|
-
false
|
78
|
-
end
|
79
|
-
|
80
|
-
def run_command(args)
|
81
|
-
boot_server unless server_running?
|
82
|
-
|
83
|
-
application, client = UNIXSocket.pair
|
84
|
-
|
85
|
-
server = UNIXSocket.open(env.socket_name)
|
86
|
-
server.send_io client
|
87
|
-
server.puts rails_env_for(args.first)
|
88
|
-
|
89
|
-
application.send_io STDOUT
|
90
|
-
application.send_io STDERR
|
91
|
-
application.send_io stdin_slave
|
92
|
-
|
93
|
-
application.puts args.length
|
94
|
-
|
95
|
-
args.each do |arg|
|
96
|
-
application.puts arg.length
|
97
|
-
application.write arg
|
98
|
-
end
|
99
|
-
|
100
|
-
pid = server.gets.chomp
|
101
|
-
|
102
|
-
# We must not close the client socket until we are sure that the application has
|
103
|
-
# received the FD. Otherwise the FD can end up getting closed while it's in the server
|
104
|
-
# socket buffer on OS X. This doesn't happen on Linux.
|
105
|
-
client.close
|
106
|
-
|
107
|
-
if pid.empty?
|
108
|
-
false
|
109
|
-
else
|
110
|
-
forward_signals(pid.to_i)
|
111
|
-
application.read # FIXME: receive exit status from server
|
112
|
-
true
|
113
|
-
end
|
114
|
-
rescue Errno::ECONNRESET
|
115
|
-
false
|
116
|
-
ensure
|
117
|
-
application.close if application
|
118
|
-
server.close if server
|
119
|
-
end
|
120
|
-
|
121
|
-
def rails_env_for(command_name)
|
122
|
-
command = Spring.command(command_name)
|
123
|
-
|
124
|
-
if command.respond_to?(:env)
|
125
|
-
command.env
|
126
|
-
else
|
127
|
-
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def stdin_slave
|
132
|
-
master, slave = PTY.open
|
133
|
-
|
134
|
-
# Sadly I cannot find a way to achieve this without shelling out to stty, or
|
135
|
-
# using a C extension library. [Ruby does not have direct support for calling
|
136
|
-
# tcsetattr().] We don't want to use a C extension library so
|
137
|
-
# that spring can be used by Rails in the future.
|
138
|
-
system "stty -icanon -echo"
|
139
|
-
at_exit { system "stty sane" }
|
140
|
-
|
141
|
-
Thread.new { master.write STDIN.read(1) until STDIN.closed? }
|
142
|
-
|
143
|
-
slave
|
144
|
-
end
|
145
|
-
|
146
|
-
def forward_signals(pid)
|
147
|
-
(FORWARDED_SIGNALS & Signal.list.keys).each do |sig|
|
148
|
-
trap(sig) { Process.kill(sig, pid) }
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|