From b7f09932c1624476b329cec7d4cfe7b98db598ef Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Thu, 12 Dec 2024 13:58:05 +1300 Subject: [PATCH] Improved logging when child process fails. --- lib/async/container/generic.rb | 9 ++++++++- lib/async/container/group.rb | 3 ++- lib/async/container/process.rb | 26 ++++++++++++++++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/async/container/generic.rb b/lib/async/container/generic.rb index bf78d13..185ae57 100644 --- a/lib/async/container/generic.rb +++ b/lib/async/container/generic.rb @@ -107,13 +107,20 @@ def wait_until_ready Console.debug(self) do |buffer| buffer.puts "Waiting for ready:" @state.each do |child, state| - buffer.puts "\t#{child.class}: #{state.inspect}" + buffer.puts "\t#{child.inspect}: #{state}" end end self.sleep if self.status?(:ready) + Console.logger.debug(self) do |buffer| + buffer.puts "All ready:" + @state.each do |child, state| + buffer.puts "\t#{child.inspect}: #{state}" + end + end + return true end end diff --git a/lib/async/container/group.rb b/lib/async/container/group.rb index 7d28d1a..eaafa04 100644 --- a/lib/async/container/group.rb +++ b/lib/async/container/group.rb @@ -137,7 +137,8 @@ def wait_for(channel) protected def wait_for_children(duration = nil) - Console.debug(self, "Waiting for children...", duration: duration) + Console.debug(self, "Waiting for children...", duration: duration, running: @running) + if !@running.empty? # Maybe consider using a proper event loop here: readable, _, _ = ::IO.select(@running.keys, nil, nil, duration) diff --git a/lib/async/container/process.rb b/lib/async/container/process.rb index d05f4c7..f89d925 100644 --- a/lib/async/container/process.rb +++ b/lib/async/container/process.rb @@ -122,10 +122,12 @@ def name= value # A human readable representation of the process. # @returns [String] - def to_s - "\#<#{self.class} #{@name}>" + def inspect + "\#<#{self.class} name=#{@name.inspect} status=#{@status.inspect} pid=#{@pid.inspect}>" end + alias to_s inspect + # Invoke {#terminate!} and then {#wait} for the child process to exit. def close self.terminate! @@ -149,22 +151,26 @@ def terminate! end # Wait for the child process to exit. + # @asynchronous This method may block. + # # @returns [::Process::Status] The process exit status. def wait if @pid && @status.nil? - _, @status = ::Process.wait2(@pid, ::Process::WNOHANG) - - if @status.nil? - sleep(0.01) - _, @status = ::Process.wait2(@pid, ::Process::WNOHANG) - end + Console.debug(self, "Waiting for process to exit...", pid: @pid) - if @status.nil? + _, @status = ::Process.wait2(@pid, ::Process::WNOHANG) + + while @status.nil? Console.warn(self) {"Process #{@pid} is blocking, has it exited?"} - _, @status = ::Process.wait2(@pid) + + sleep(0.1) + + _, @status = ::Process.wait2(@pid, ::Process::WNOHANG) end end + Console.debug(self, "Process exited.", pid: @pid, status: @status) + return @status end end