tork 19.4.0 → 19.5.0
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.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/VERSION.md +191 -102
- data/bin/tork +4 -3
- data/bin/tork-driver +5 -2
- data/bin/tork-engine +5 -2
- data/bin/tork-herald +3 -3
- data/bin/tork-master +5 -2
- data/bin/tork-notify +3 -2
- data/bin/tork-remote +4 -9
- data/bin/tork-runner +86 -0
- data/lib/tork/bridge.rb +66 -0
- data/lib/tork/cliapp.rb +21 -13
- data/lib/tork/config/rails/worker.rb +1 -1
- data/lib/tork/engine.rb +3 -12
- data/lib/tork/server.rb +31 -37
- data/lib/tork/version.rb +1 -1
- data/man/index.html +1 -1
- data/man/man0/README.html +5 -3
- data/man/man0/README.md +6 -2
- data/man/man0/VERSION.html +156 -102
- data/man/man0/VERSION.md +191 -102
- data/man/man1/tork-driver.1 +7 -2
- data/man/man1/tork-driver.1.html +5 -2
- data/man/man1/tork-engine.1 +7 -2
- data/man/man1/tork-engine.1.html +5 -2
- data/man/man1/tork-herald.1 +1 -1
- data/man/man1/tork-herald.1.html +1 -1
- data/man/man1/tork-master.1 +7 -2
- data/man/man1/tork-master.1.html +5 -2
- data/man/man1/tork-notify.1 +1 -1
- data/man/man1/tork-notify.1.html +1 -1
- data/man/man1/tork-remote.1 +4 -10
- data/man/man1/tork-remote.1.html +4 -5
- data/man/man1/tork-runner.1 +44 -0
- data/man/man1/tork-runner.1.html +14 -0
- data/man/man1/tork.1 +5 -3
- data/man/man1/tork.1.html +3 -2
- data/man/style.css +1 -1
- data/tork.gemspec +2 -1
- metadata +11 -5
data/bin/tork
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK 1 2013-11-
|
4
|
+
# TORK 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -13,7 +13,8 @@ tork - Continuous testing tool for Ruby
|
|
13
13
|
|
14
14
|
## DESCRIPTION
|
15
15
|
|
16
|
-
This program
|
16
|
+
This program can be thought of as an interactive version of tork-runner(1).
|
17
|
+
It functions as a rudimentary command-line user interface to tork-driver(1).
|
17
18
|
|
18
19
|
First, it applies the given *CONFIG* values, which are either (1) paths to
|
19
20
|
directories that contain configuration files or (2) names of configuration
|
@@ -111,7 +112,7 @@ This program can be controlled remotely by multiple tork-remote(1) instances.
|
|
111
112
|
|
112
113
|
## SEE ALSO
|
113
114
|
|
114
|
-
tork(1), tork-driver(1), tork-master(1)
|
115
|
+
tork-runner(1), tork-driver(1), tork-master(1)
|
115
116
|
|
116
117
|
[factory_girl]: https://github.com/thoughtbot/factory_girl
|
117
118
|
[memory_test_fix]: https://github.com/stepahn/memory_test_fix
|
data/bin/tork-driver
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK-DRIVER 1 2013-11-
|
4
|
+
# TORK-DRIVER 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -20,7 +20,10 @@ This program can be controlled remotely by multiple tork-remote(1) instances.
|
|
20
20
|
### Input
|
21
21
|
|
22
22
|
This program reads the following commands, which are single-line JSON arrays,
|
23
|
-
from stdin and performs the actions
|
23
|
+
from stdin and then performs the associated actions. For lines read from
|
24
|
+
stdin that are single-line JSON arrays, it splits each of them into an array
|
25
|
+
of words, using the same word-splitting algorithm as sh(1), before processing
|
26
|
+
them. For example, the line `a "b c"` is split into the `["a", "b c"]` array.
|
24
27
|
|
25
28
|
`["run_all_test_files"]`
|
26
29
|
Runs all test files found within and beneath the current working directory.
|
data/bin/tork-engine
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK-ENGINE 1 2013-11-
|
4
|
+
# TORK-ENGINE 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -20,7 +20,10 @@ This program can be controlled remotely by multiple tork-remote(1) instances.
|
|
20
20
|
### Input
|
21
21
|
|
22
22
|
This program reads the following commands, which are single-line JSON arrays,
|
23
|
-
from stdin and performs the actions
|
23
|
+
from stdin and then performs the associated actions. For lines read from
|
24
|
+
stdin that are single-line JSON arrays, it splits each of them into an array
|
25
|
+
of words, using the same word-splitting algorithm as sh(1), before processing
|
26
|
+
them. For example, the line `a "b c"` is split into the `["a", "b c"]` array.
|
24
27
|
|
25
28
|
`["reabsorb_overhead"]`
|
26
29
|
Stops any test files that are currently running, reabsorbs the test
|
data/bin/tork-herald
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK-HERALD 1 2013-11-
|
4
|
+
# TORK-HERALD 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -37,7 +37,7 @@ require 'json'
|
|
37
37
|
STDOUT.sync = true # flush puts() output immediately after writing
|
38
38
|
|
39
39
|
require 'listen'
|
40
|
-
Listen.to
|
40
|
+
Listen.to! '.', :relative_paths => true do |modified, added, removed|
|
41
41
|
files = modified + added
|
42
42
|
puts JSON.dump(files) unless files.empty?
|
43
|
-
end
|
43
|
+
end
|
data/bin/tork-master
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK-MASTER 1 2013-11-
|
4
|
+
# TORK-MASTER 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -23,7 +23,10 @@ This program can be controlled remotely by multiple tork-remote(1) instances.
|
|
23
23
|
### Input
|
24
24
|
|
25
25
|
This program reads the following commands, which are single-line JSON arrays,
|
26
|
-
from stdin and performs the actions
|
26
|
+
from stdin and then performs the associated actions. For lines read from
|
27
|
+
stdin that are single-line JSON arrays, it splits each of them into an array
|
28
|
+
of words, using the same word-splitting algorithm as sh(1), before processing
|
29
|
+
them. For example, the line `a "b c"` is split into the `["a", "b c"]` array.
|
27
30
|
|
28
31
|
`["test",` *test_file*`,` *line_numbers*`]`
|
29
32
|
Forks a worker process to run tests that correspond to the given
|
data/bin/tork-notify
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
=begin =======================================================================
|
3
3
|
|
4
|
-
# TORK-NOTIFY 1 2013-11-
|
4
|
+
# TORK-NOTIFY 1 2013-11-30 19.5.0
|
5
5
|
|
6
6
|
## NAME
|
7
7
|
|
@@ -58,7 +58,8 @@ IO.popen('tork-remote tork-engine', 'r+') do |remote|
|
|
58
58
|
statistics = File.readlines(log_file).grep(/^\d+ \w+,/).join.
|
59
59
|
gsub(/\e\[\d+(;\d+)?m/, '') # strip ANSI SGR escape codes
|
60
60
|
|
61
|
-
|
61
|
+
# run in background; see http://stackoverflow.com/q/16745840
|
62
|
+
Thread.new(icon, title, statistics) do |icon, title, statistics|
|
62
63
|
system 'notify-send', '-i', icon, title, statistics or
|
63
64
|
system 'growlnotify', '-a', 'Xcode', '-m', statistics, title or
|
64
65
|
system 'xmessage', '-timeout', '5', '-title', title, statistics or
|
data/bin/tork-remote
CHANGED
@@ -13,15 +13,10 @@ tork-remote - controls tork(1) programs
|
|
13
13
|
|
14
14
|
## DESCRIPTION
|
15
15
|
|
16
|
-
This program
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
split into an array of words, using the same word-splitting algorithm as
|
21
|
-
sh(1), before being sent to the *PROGRAM* as a single-line JSON message.
|
22
|
-
|
23
|
-
If the *PROGRAM* sends any messages in response, then they are printed to
|
24
|
-
stdout if they are valid single-line JSON messages or to stderr otherwise.
|
16
|
+
This program reads lines from its stdin and sends them to the given *PROGRAM*,
|
17
|
+
which must already be running in the same working directory as this program.
|
18
|
+
It also prints lines, received in response, from the given *PROGRAM* either
|
19
|
+
to stdout if they are valid single-line JSON arrays or to stderr otherwise.
|
25
20
|
|
26
21
|
## OPTIONS
|
27
22
|
|
data/bin/tork-runner
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin =======================================================================
|
3
|
+
|
4
|
+
# TORK-RUNNER 1 2013-11-30 19.5.0
|
5
|
+
|
6
|
+
## NAME
|
7
|
+
|
8
|
+
tork-runner - runs tests once, non-interactively
|
9
|
+
|
10
|
+
## SYNOPSIS
|
11
|
+
|
12
|
+
`tork-runner` [*OPTION*]... [*TEST\_FILE\_GLOB*]...
|
13
|
+
|
14
|
+
## DESCRIPTION
|
15
|
+
|
16
|
+
This program can be thought of as a non-interactive version of tork(1). It
|
17
|
+
runs all test files that match the given *TEST\_FILE\_GLOB*s and then exits
|
18
|
+
with a nonzero status if any tests failed. If none are given, it runs all
|
19
|
+
test files known to `Tork::Driver::TEST_FILE_GLOBBERS` in tork-driver(1).
|
20
|
+
|
21
|
+
### Output
|
22
|
+
|
23
|
+
This program prints the following messages to stdout.
|
24
|
+
|
25
|
+
`>>` *failed\_test\_log\_file* `<<`
|
26
|
+
This message will be followed by the content of *failed\_test\_log\_file*.
|
27
|
+
|
28
|
+
*T* `tested,` *P* `passed,` *F* `failed`
|
29
|
+
*T* test files were tested and *P* of them passed but *F* of them failed.
|
30
|
+
|
31
|
+
## OPTIONS
|
32
|
+
|
33
|
+
`-h`, `--help`
|
34
|
+
Show this help manual.
|
35
|
+
|
36
|
+
## EXIT STATUS
|
37
|
+
|
38
|
+
0
|
39
|
+
All test files passed.
|
40
|
+
|
41
|
+
1
|
42
|
+
One or more test files failed.
|
43
|
+
|
44
|
+
## ENVIRONMENT
|
45
|
+
|
46
|
+
See tork(1).
|
47
|
+
|
48
|
+
## SEE ALSO
|
49
|
+
|
50
|
+
tork(1), tork-driver(1)
|
51
|
+
|
52
|
+
=end =========================================================================
|
53
|
+
|
54
|
+
$0 = File.basename(__FILE__) # for easier identification in ps(1) output
|
55
|
+
|
56
|
+
require 'binman'
|
57
|
+
BinMan.help
|
58
|
+
|
59
|
+
require 'json'
|
60
|
+
IO.popen('tork-driver', 'w+') do |driver|
|
61
|
+
# tell tork to run the given test files
|
62
|
+
# or run known test files if none given
|
63
|
+
test_files = Dir[*ARGV]
|
64
|
+
command =
|
65
|
+
if test_files.empty?
|
66
|
+
[:run_all_test_files]
|
67
|
+
else
|
68
|
+
[:run_test_files, test_files]
|
69
|
+
end
|
70
|
+
driver.puts JSON.dump(command)
|
71
|
+
|
72
|
+
# track test runs & exit when finished
|
73
|
+
tested, passed, failed = 0, 0, []
|
74
|
+
while line = driver.gets
|
75
|
+
response = JSON.load(line)
|
76
|
+
case response.first.to_sym
|
77
|
+
when :test then tested += 1
|
78
|
+
when :pass then passed += 1
|
79
|
+
when :fail then failed << response[3]
|
80
|
+
when :idle then
|
81
|
+
puts failed.map {|log| [nil, ">> #{log} <<", File.read(log)] }, nil,
|
82
|
+
"#{tested} tested, #{passed} passed, #{failed.count} failed"
|
83
|
+
exit failed.empty?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/tork/bridge.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Tork
|
2
|
+
# Wrapper for IO.popen() that automatically re-establishes itself
|
3
|
+
# whenever the child process terminates extraneously, on its own.
|
4
|
+
class Bridge
|
5
|
+
|
6
|
+
def initialize command
|
7
|
+
@command = command
|
8
|
+
connect
|
9
|
+
end
|
10
|
+
|
11
|
+
def disconnect
|
12
|
+
return unless @guardian.alive?
|
13
|
+
|
14
|
+
# prevent guardian from reconnecting bridge while we disconnect it
|
15
|
+
@guardian.exit
|
16
|
+
|
17
|
+
# this should be enough to stop programs that use Tork::Server#loop
|
18
|
+
# because their IO.select() loop terminates on the closing of STDIN
|
19
|
+
@io.close_write
|
20
|
+
|
21
|
+
# but some programs like tork-herald(1) need to be killed explicitly
|
22
|
+
# because they do not follow our convention of exiting on STDIN close
|
23
|
+
Process.kill :SIGTERM, @io.pid
|
24
|
+
Process.waitpid @io.pid
|
25
|
+
|
26
|
+
# this will block until the child process has exited so we must kill it
|
27
|
+
# explicitly (as above) to ensure that this program does not hang here
|
28
|
+
@io.close_read
|
29
|
+
|
30
|
+
rescue IOError, SystemCallError
|
31
|
+
# IOError happens if the child process' pipes are already closed
|
32
|
+
# SystemCallError happens if the child process is already dead
|
33
|
+
end
|
34
|
+
|
35
|
+
def reconnect
|
36
|
+
disconnect
|
37
|
+
connect
|
38
|
+
end
|
39
|
+
|
40
|
+
# Allows this object to be passed directly
|
41
|
+
# into IO.select() and Tork::Server#tell().
|
42
|
+
def to_io
|
43
|
+
@io
|
44
|
+
end
|
45
|
+
|
46
|
+
# Allows this object to be treated as IO.
|
47
|
+
def method_missing *args, &block
|
48
|
+
@io.__send__ *args, &block
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def connect
|
54
|
+
@io = IO.popen(@command, 'r+')
|
55
|
+
|
56
|
+
# automatically reconnect the bridge when the child process terminates
|
57
|
+
@guardian = Thread.new do
|
58
|
+
Process.waitpid @io.pid
|
59
|
+
warn "#{$0}: repairing collapsed bridge: #{@command} #{$?}"
|
60
|
+
sleep 1 # avoid spamming the CPU by waiting a bit before reconnecting
|
61
|
+
connect # no need to disconnect because child process is already dead
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
data/lib/tork/cliapp.rb
CHANGED
@@ -24,6 +24,11 @@ class CLIApp < Server
|
|
24
24
|
|
25
25
|
protected
|
26
26
|
|
27
|
+
def join client
|
28
|
+
super
|
29
|
+
help client
|
30
|
+
end
|
31
|
+
|
27
32
|
def recv client, message
|
28
33
|
case client
|
29
34
|
when @driver
|
@@ -51,23 +56,26 @@ protected
|
|
51
56
|
tell @clients, message, false
|
52
57
|
end
|
53
58
|
else
|
54
|
-
key
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
quit if cmd == :quit
|
59
|
-
call = Array(cmd) + args
|
60
|
-
tell @clients, "Sending #{call.inspect} command...", false
|
61
|
-
send @driver, call
|
59
|
+
key = message.shift.lstrip[0,1].downcase
|
60
|
+
cmd = Array(COMMANDS.fetch(key, [:help, client])) + message
|
61
|
+
if respond_to? cmd.first, true
|
62
|
+
__send__(*cmd)
|
62
63
|
else
|
63
|
-
|
64
|
-
|
65
|
-
desc = Array(cmd).join(' with ').to_s.tr('_', ' ')
|
66
|
-
tell @client, "Type #{key} then ENTER to #{desc}.", false
|
67
|
-
end
|
64
|
+
tell @clients, "Sending #{cmd.inspect} command...", false
|
65
|
+
send @driver, cmd
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|
71
69
|
|
70
|
+
private
|
71
|
+
|
72
|
+
def help client
|
73
|
+
COMMANDS.each do |key, cmd|
|
74
|
+
desc = Array(cmd).join(' with ').to_s.tr('_', ' ')
|
75
|
+
tell client, "Type #{key} then ENTER to #{desc}.", false
|
76
|
+
end
|
77
|
+
tell client, 'Type h then ENTER to see this message.', false
|
78
|
+
end
|
79
|
+
|
72
80
|
end
|
73
81
|
end
|
@@ -10,7 +10,7 @@ if defined? ActiveRecord::Base
|
|
10
10
|
elsif base.respond_to? :connection_pool # rails >= 2.2.1
|
11
11
|
base.connection_pool.spec.config
|
12
12
|
else
|
13
|
-
warn "#{$0}: config/rails/worker:
|
13
|
+
warn "#{$0}: config/rails/worker: could not read connection information"
|
14
14
|
{}
|
15
15
|
end
|
16
16
|
|
data/lib/tork/engine.rb
CHANGED
@@ -17,15 +17,14 @@ class Engine < Server
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def loop
|
20
|
-
|
20
|
+
@master = popen('tork-master')
|
21
21
|
super
|
22
22
|
ensure
|
23
|
-
|
23
|
+
pclose @master
|
24
24
|
end
|
25
25
|
|
26
26
|
def reabsorb_overhead
|
27
|
-
|
28
|
-
create_master
|
27
|
+
@master.reconnect
|
29
28
|
|
30
29
|
# re-dispatch the previously dispatched files to the new master
|
31
30
|
previous = @queued_test_files.to_a
|
@@ -122,13 +121,5 @@ private
|
|
122
121
|
map {|change| change.position + 1 }.uniq
|
123
122
|
end
|
124
123
|
|
125
|
-
def create_master
|
126
|
-
@master = popen('tork-master')
|
127
|
-
end
|
128
|
-
|
129
|
-
def destroy_master
|
130
|
-
pclose @master
|
131
|
-
end
|
132
|
-
|
133
124
|
end
|
134
125
|
end
|
data/lib/tork/server.rb
CHANGED
@@ -2,6 +2,7 @@ require 'socket'
|
|
2
2
|
require 'json'
|
3
3
|
require 'shellwords'
|
4
4
|
require 'set'
|
5
|
+
require 'tork/bridge'
|
5
6
|
|
6
7
|
module Tork
|
7
8
|
class Server
|
@@ -11,46 +12,42 @@ class Server
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def initialize
|
15
|
+
begin
|
16
|
+
@welcome = UNIXServer.open(address = Server.address)
|
17
|
+
# UNIX domain socket files are not automatically deleted on close
|
18
|
+
at_exit { File.delete address if File.socket? address }
|
19
|
+
rescue Errno::EADDRINUSE
|
20
|
+
# another instance of this program is already running in the same
|
21
|
+
# directory so become a remote control for it rather than exiting
|
22
|
+
warn "#{$0}: remotely controlling existing instance..."
|
23
|
+
exec 'tork-remote', $0
|
24
|
+
end
|
25
|
+
|
14
26
|
# only JSON messages are supposed to be emitted on STDOUT
|
15
27
|
# so make puts() in the user code write to STDERR instead
|
16
28
|
@stdout = STDOUT.dup
|
17
29
|
STDOUT.reopen STDERR
|
18
30
|
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@address = Server.address
|
31
|
+
@servers = Set.new.add(@welcome)
|
32
|
+
@clients = Set.new; join STDIN # parent process connected on STDIN
|
22
33
|
end
|
23
34
|
|
24
35
|
def loop
|
25
|
-
begin
|
26
|
-
server = UNIXServer.open(@address)
|
27
|
-
rescue SystemCallError => error
|
28
|
-
warn "#{$0}: #{error}; retrying in #{timeout = 1 + rand(10)} seconds..."
|
29
|
-
sleep timeout
|
30
|
-
retry
|
31
|
-
end
|
32
|
-
|
33
36
|
catch :quit do
|
34
|
-
@servers.add server
|
35
37
|
while @clients.include? STDIN
|
36
38
|
IO.select((@servers + @clients).to_a).first.each do |stream|
|
37
|
-
|
38
|
-
|
39
|
-
if stream == server
|
40
|
-
@clients.add stream.accept
|
39
|
+
if stream == @welcome
|
40
|
+
join stream.accept
|
41
41
|
|
42
42
|
elsif (stream.eof? rescue true)
|
43
|
-
|
43
|
+
part stream
|
44
44
|
|
45
|
-
elsif @command = hear(stream, stream.gets)
|
45
|
+
elsif @command = hear(stream, stream.gets) and not @command.empty?
|
46
46
|
recv stream, @command
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
|
-
ensure
|
52
|
-
# UNIX domain socket files are not deleted automatically upon closing
|
53
|
-
File.delete @address if File.socket? @address
|
54
51
|
end
|
55
52
|
|
56
53
|
def quit
|
@@ -59,6 +56,14 @@ class Server
|
|
59
56
|
|
60
57
|
protected
|
61
58
|
|
59
|
+
def join client
|
60
|
+
@clients.add client
|
61
|
+
end
|
62
|
+
|
63
|
+
def part client
|
64
|
+
@clients.delete client
|
65
|
+
end
|
66
|
+
|
62
67
|
# Returns nil if the message received was not meant for processing.
|
63
68
|
def hear sender, message
|
64
69
|
JSON.load message
|
@@ -73,7 +78,9 @@ protected
|
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
81
|
+
# Sets the @client variable to the client we are currently serving.
|
76
82
|
def recv client, command
|
83
|
+
@client = client
|
77
84
|
__send__(*command)
|
78
85
|
rescue => error
|
79
86
|
tell client, error
|
@@ -93,7 +100,7 @@ protected
|
|
93
100
|
end
|
94
101
|
|
95
102
|
targets =
|
96
|
-
if one_or_more_clients.
|
103
|
+
if one_or_more_clients.respond_to? :to_io
|
97
104
|
[one_or_more_clients]
|
98
105
|
else
|
99
106
|
Array(one_or_more_clients)
|
@@ -113,26 +120,13 @@ protected
|
|
113
120
|
end
|
114
121
|
|
115
122
|
def popen command
|
116
|
-
child =
|
123
|
+
child = Bridge.new(command)
|
117
124
|
@servers.add child
|
118
125
|
child
|
119
126
|
end
|
120
127
|
|
121
128
|
def pclose child
|
122
|
-
|
123
|
-
|
124
|
-
# this should be enough to stop programs that use Tork::Server#loop
|
125
|
-
# because their IO.select() loop terminates on the closing of STDIN
|
126
|
-
child.close_write
|
127
|
-
|
128
|
-
# but some programs like tork-herald(1) need to be killed explicitly
|
129
|
-
# because they do not follow our convention of exiting on STDIN close
|
130
|
-
Process.kill :SIGTERM, child.pid
|
131
|
-
Process.waitpid child.pid
|
132
|
-
|
133
|
-
# this will block until the child process has exited so we must kill it
|
134
|
-
# explicitly (as above) to ensure that this program does not hang here
|
135
|
-
child.close_read
|
129
|
+
child.disconnect if @servers.delete? child
|
136
130
|
end
|
137
131
|
|
138
132
|
end
|