I'd like to know how to catch exceptions from Open3.popen3
on Ruby.
require "open3"
begin
Open3.popen3("./somebinary") {|i,o,e,t|
# IO.popen("./somebinary") {|i|
$stderr.puts "popen"
i.puts "some string"
}
rescue StandardError => e
$stderr.puts e.message
$stderr.puts e.backtrace.inspect
$stderr.puts "error"
exit(1)
end
The problem is that the binary executable is of a wrong architecture and doesn't run on the local machine. When invoked from the command line, like so ./somebinary
, you see the error message.
With popen
, the error is caught by the rescue clause, but not with popen3
.
If the rescue
clause didn't have StandardError => e
, the clause is entered, but you can't know the reason for the error because all you see is the message "error" from $stderr.puts "error"
. With popen3
, the stderr from the command line vanishes!
I'm using ruby 3.0.1p64 on macOS 11.3.1 .
A complete example
~/tmp $ ./somebinary
dyld: Library not loaded: /usr/local/opt/gcc/lib/gcc/10/libgfortran.5.dylib
Referenced from: /Users/furue/tmp/./somebinary
Reason: image not found
fish: Job 1, './somebinary' terminated by signal SIGABRT (Abort)
~/tmp [134] $ ruby --version
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [arm64-darwin20]
~/tmp $ cat try-popen3.rb
require "open3"
begin
Open3.popen3("./somebinary") {|i,o,e,t|
$stderr.puts "in popen . . . "
i.puts "some string"
}
rescue
$stderr.puts "error in rescue . . . "
exit(1)
end
~/tmp $ ruby try-popen3.rb
in popen . . .
~/tmp $ cat try-popen3-standarderror.rb
require "open3"
begin
Open3.popen3("./somebinary") {|i,o,e,t|
$stderr.puts "in popen . . . "
i.puts "some string"
}
rescue StandardError => e
$stderr.puts e.message
$stderr.puts e.backtrace.inspect
$stderr.puts "error in rescue . . . "
exit(1)
end
~/tmp $ ruby try-popen3-standarderror.rb
in popen . . .
~/tmp $ cat try-popen.rb
require "open3"
begin
IO.popen("./somebinary") {|i|
$stderr.puts "in popen . . . "
i.puts "some string"
}
rescue
$stderr.puts "error in rescue . . . "
exit(1)
end
~/tmp $ ruby try-popen.rb
in popen . . .
dyld: Library not loaded: /usr/local/opt/gcc/lib/gcc/10/libgfortran.5.dylib
Referenced from: /Users/furue/tmp/./somebinary
Reason: image not found
error in rescue . . .
~/tmp [1] $ cat try-popen-standarderror.rb
require "open3"
begin
IO.popen("./somebinary") {|i|
$stderr.puts "in popen . . . "
i.puts "some string"
}
rescue StandardError => e
$stderr.puts e.message
$stderr.puts e.backtrace.inspect
$stderr.puts "error in rescue . . . "
exit(1)
end
~/tmp $ ruby try-popen-standarderror.rb
in popen . . .
dyld: Library not loaded: /usr/local/opt/gcc/lib/gcc/10/libgfortran.5.dylib
Referenced from: /Users/furue/tmp/./somebinary
Reason: image not found
not opened for writing
["try-popen-standarderror.rb:5:in `write'", "try-popen-standarderror.rb:5:in `puts'", "try-popen-standarderror.rb:5:in `block in <main>'", "try-popen-standarderror.rb:3:in `popen'", "try-popen-standarderror.rb:3:in `<main>'"]
error in rescue . . .
~/tmp [1] $