Skip to content

Commit

Permalink
Merge pull request #313 from ruby/katei/fix-pipe-stuck
Browse files Browse the repository at this point in the history
build: Fix pipe stuck without --verbose and better progress indicator
  • Loading branch information
kateinoigakukun authored Nov 22, 2023
2 parents 0a3bdcf + f0dbac1 commit 5a28621
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 25 deletions.
1 change: 1 addition & 0 deletions Steepfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ target :lib do
library "open-uri"
library "uri"
library "shellwords"
library "io-console"

configure_code_diagnostics(D::Ruby.default)
end
119 changes: 96 additions & 23 deletions lib/ruby_wasm/build.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,67 @@ def initialize(verbose: false)
@github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil
end

def system(*args, chdir: nil, out: nil, env: nil)
def system(*args, chdir: nil, env: nil)
require "open3"

_print_command(args, env)

if @verbose
out ||= $stdout
else
# Capture stdout by default
out_pipe = IO.pipe
out = out_pipe[1]
end
# @type var kwargs: Hash[Symbol, untyped]
kwargs = { exception: true, out: out }
kwargs = {}
kwargs[:chdir] = chdir if chdir
begin
if env
Kernel.system(env, *args.to_a.map(&:to_s), **kwargs)

args = args.to_a.map(&:to_s)
# TODO: Remove __skip__ once we have open3 RBS definitions.
__skip__ =
if @verbose || !$stdout.tty?
kwargs[:exception] = true
if env
Kernel.system(env, *args, **kwargs)
else
Kernel.system(*args, **kwargs)
end
else
Kernel.system(*args.to_a.map(&:to_s), **kwargs)
printer = StatusPrinter.new
block =
proc do |stdin, stdout, stderr, wait_thr|
mux = Mutex.new
out = String.new
err = String.new
readers =
[
[stdout, :stdout, out],
[stderr, :stderr, err]
].map do |io, name, str|
reader =
Thread.new do
while (line = io.gets)
mux.synchronize do
printer.send(name, line)
str << line
end
end
end
reader.report_on_exception = false
reader
end

readers.each(&:join)

[out, err, wait_thr.value]
end
begin
if env
Open3.popen3(env, *args, **kwargs, &block)
else
Open3.popen3(*args, **kwargs, &block)
end
ensure
printer.done
end
end
ensure
out.close if out_pipe
end
rescue => e
if out_pipe
# Print the output of the failed command
puts out_pipe[0].read
end
$stdout.flush
$stderr.puts "Try running with `rake --verbose` for more complete output."
raise e
end

Expand All @@ -58,9 +91,7 @@ def begin_section(klass, name, note)

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

Expand Down Expand Up @@ -98,4 +129,46 @@ def _print_command(args, env)
print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n"
end
end

# Human readable status printer for the build.
class StatusPrinter
def initialize
@mutex = Mutex.new
@counter = 0
@indicators = "|/-\\"
end

def stdout(message)
require "io/console"
@mutex.synchronize do
$stdout.print "\e[K"
first_line = message.lines(chomp: true).first || ""

# Make sure we don't line-wrap the output
size =
__skip__ =
IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize
terminal_width = size[1].to_i.nonzero? || 80
width_limit = terminal_width / 2 - 3

if first_line.length > width_limit
first_line = (first_line[0..width_limit - 5] || "") + "..."
end
indicator = @indicators[@counter] || " "
to_print = " " + indicator + " " + first_line
$stdout.print to_print
$stdout.print "\e[1A\n"
@counter += 1
@counter = 0 if @counter >= @indicators.length
end
end

def stderr(message)
@mutex.synchronize { $stdout.print message }
end

def done
@mutex.synchronize { $stdout.print "\e[K" }
end
end
end
6 changes: 5 additions & 1 deletion lib/ruby_wasm/build/product/wasi_vfs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ def build(executor)
lib_wasi_vfs_url =
"https://github.com/kateinoigakukun/wasi-vfs/releases/download/v#{WASI_VFS_VERSION}/libwasi_vfs-wasm32-unknown-unknown.zip"
Dir.mktmpdir do |tmpdir|
executor.system "curl", "-L", lib_wasi_vfs_url, "-o", "#{tmpdir}/libwasi_vfs.zip"
executor.system "curl",
"-L",
lib_wasi_vfs_url,
"-o",
"#{tmpdir}/libwasi_vfs.zip"
executor.system "unzip", "#{tmpdir}/libwasi_vfs.zip", "-d", tmpdir
executor.mkdir_p File.dirname(lib_wasi_vfs_a)
executor.mv File.join(tmpdir, "libwasi_vfs.a"), lib_wasi_vfs_a
Expand Down
13 changes: 12 additions & 1 deletion sig/ruby_wasm/build.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ module RubyWasm
@start_times: Hash[[Class, String], Time]

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

class StatusPrinter
@mutex: Mutex
@counter: Integer
@indicators: String

def initialize: () -> void
def stdout: (String message) -> void
def stderr: (String message) -> void
def done: () -> void
end

class Downloader
def format_size: (Integer size) -> String

Expand Down

0 comments on commit 5a28621

Please sign in to comment.