diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index 836bdbae..42731d23 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -223,6 +223,19 @@ class Pry else print.call output, result end + rescue Exception => e + # Being uber-paranoid here, given that this exception arose because we couldn't + # serialize something in the user's program, let's not assume we can serialize + # the exception either. + begin + output.puts "output error: #{e.inspect}" + rescue Exception => e + if last_result_is_exception? + output.puts "output error: failed to show exception" + else + output.puts "output error: failed to show result" + end + end end # Returns true if input is "" and a command is not returning a diff --git a/test/test_pry_output.rb b/test/test_pry_output.rb new file mode 100644 index 00000000..48702534 --- /dev/null +++ b/test/test_pry_output.rb @@ -0,0 +1,30 @@ + +describe Pry do + describe "output failsafe" do + after do + Pry.config.print = Pry::DEFAULT_PRINT + end + + it "should catch serialization exceptions" do + Pry.config.print = lambda { |*a| raise "catch-22" } + + lambda { + mock_pry("1") + }.should.not.raise + end + + it "should display serialization exceptions" do + Pry.config.print = lambda { |*a| raise "catch-22" } + + mock_pry("1").should =~ /output error: #/ + end + + it "should catch errors serializing exceptions" do + Pry.config.print = lambda do |*a| + raise Exception.new("catch-22").tap{ |e| class << e; def inspect; raise e; end; end } + end + + mock_pry("1").should =~ /output error: failed to show result/ + end + end +end