Skip to content

Commit 3cc8c05

Browse files
build: Fix pipe stuck without --verbose and better progress indicator
1 parent 0a3bdcf commit 3cc8c05

File tree

3 files changed

+97
-24
lines changed

3 files changed

+97
-24
lines changed

Steepfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ target :lib do
1313
library "open-uri"
1414
library "uri"
1515
library "shellwords"
16+
library "io-console"
1617

1718
configure_code_diagnostics(D::Ruby.default)
1819
end

lib/ruby_wasm/build.rb

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,53 @@ def initialize(verbose: false)
1010
@github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil
1111
end
1212

13-
def system(*args, chdir: nil, out: nil, env: nil)
13+
def system(*args, chdir: nil, env: nil)
14+
require "open3"
15+
1416
_print_command(args, env)
1517

16-
if @verbose
17-
out ||= $stdout
18-
else
19-
# Capture stdout by default
20-
out_pipe = IO.pipe
21-
out = out_pipe[1]
22-
end
2318
# @type var kwargs: Hash[Symbol, untyped]
24-
kwargs = { exception: true, out: out }
19+
kwargs = {}
2520
kwargs[:chdir] = chdir if chdir
26-
begin
27-
if env
28-
Kernel.system(env, *args.to_a.map(&:to_s), **kwargs)
29-
else
30-
Kernel.system(*args.to_a.map(&:to_s), **kwargs)
21+
22+
args = args.to_a.map(&:to_s)
23+
# TODO: Remove __skip__ once we have open3 RBS definitions.
24+
__skip__ = if @verbose || !$stdout.tty?
25+
kwargs[:exception] = true
26+
env ? Kernel.system(env, *args, **kwargs) : Kernel.system(*args, **kwargs)
27+
else
28+
printer = StatusPrinter.new
29+
block = proc do |stdin, stdout, stderr, wait_thr|
30+
mux = Mutex.new
31+
out = String.new
32+
err = String.new
33+
readers = [[stdout, :stdout, out], [stderr, :stderr, err]].map do |io, name, str|
34+
reader = Thread.new {
35+
while (line = io.gets)
36+
mux.synchronize {
37+
printer.send(name, line)
38+
str << line
39+
}
40+
end
41+
}
42+
reader.report_on_exception = false
43+
reader
44+
end
45+
46+
readers.each(&:join)
47+
48+
[out, err, wait_thr.value]
49+
end
50+
begin
51+
env ? Open3.popen3(env, *args, **kwargs, &block) : Open3.popen3(*args, **kwargs, &block)
52+
ensure
53+
printer.done
3154
end
32-
ensure
33-
out.close if out_pipe
3455
end
56+
3557
rescue => e
36-
if out_pipe
37-
# Print the output of the failed command
38-
puts out_pipe[0].read
39-
end
4058
$stdout.flush
59+
$stderr.puts "Try running with `rake --verbose` for more complete output."
4160
raise e
4261
end
4362

@@ -58,9 +77,7 @@ def begin_section(klass, name, note)
5877

5978
def end_section(klass, name)
6079
took = Time.now - @start_times[[klass, name]]
61-
if @github_actions_markup
62-
puts "::endgroup::"
63-
end
80+
puts "::endgroup::" if @github_actions_markup
6481
puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m"
6582
end
6683

@@ -98,4 +115,48 @@ def _print_command(args, env)
98115
print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n"
99116
end
100117
end
118+
119+
# Human readable status printer for the build.
120+
class StatusPrinter
121+
def initialize
122+
@mutex = Mutex.new
123+
@counter = 0
124+
@indicators = "|/-\\"
125+
end
126+
127+
def stdout(message)
128+
require "io/console"
129+
@mutex.synchronize {
130+
$stdout.print "\e[K"
131+
first_line = message.lines(chomp: true).first || ""
132+
133+
# Make sure we don't line-wrap the output
134+
size = __skip__ = IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize
135+
terminal_width = size[1].to_i.nonzero? || 80
136+
width_limit = terminal_width / 2 - 3
137+
138+
if first_line.length > width_limit
139+
first_line = (first_line[0..width_limit - 5] || "") + "..."
140+
end
141+
indicator = @indicators[@counter] || " "
142+
to_print = " " + indicator + " " + first_line
143+
$stdout.print to_print
144+
$stdout.print "\e[1A\n"
145+
@counter += 1
146+
@counter = 0 if @counter >= @indicators.length
147+
}
148+
end
149+
150+
def stderr(message)
151+
@mutex.synchronize {
152+
$stdout.print message
153+
}
154+
end
155+
156+
def done
157+
@mutex.synchronize {
158+
$stdout.print "\e[K"
159+
}
160+
end
161+
end
101162
end

sig/ruby_wasm/build.rbs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ module RubyWasm
227227
@start_times: Hash[[Class, String], Time]
228228

229229
def initialize: (?verbose: bool) -> void
230-
def system: (*_ToS args, ?chdir: String?, ?out: Kernel::redirect_fd?, ?env: Hash[String, String]?) -> void
230+
def system: (*_ToS args, ?chdir: String?, ?env: Hash[String, String]?) -> void
231231
def rm_rf: (FileUtils::pathlist list) -> void
232232
def rm_f: (FileUtils::pathlist list) -> void
233233
def cp_r: (FileUtils::pathlist src, path dest) -> void
@@ -241,6 +241,17 @@ module RubyWasm
241241
private def _print_command: (Array[_ToS] command, Hash[String, String]? env) -> void
242242
end
243243

244+
class StatusPrinter
245+
@mutex: Mutex
246+
@counter: Integer
247+
@indicators: String
248+
249+
def initialize: () -> void
250+
def stdout: (String message) -> void
251+
def stderr: (String message) -> void
252+
def done: () -> void
253+
end
254+
244255
class Downloader
245256
def format_size: (Integer size) -> String
246257

0 commit comments

Comments
 (0)