Skip to content

Commit

Permalink
Fix parsing gdb output on Ubuntu 16.04, x86_64, gdb 7.11.1
Browse files Browse the repository at this point in the history
  • Loading branch information
FooBarWidget committed Nov 24, 2016
1 parent 3c4c1bc commit 8fc88f3
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 16 deletions.
27 changes: 15 additions & 12 deletions lib/crash_watch/gdb_controller.rb
Expand Up @@ -150,8 +150,8 @@ def wait_until_exit

while true
result = execute("continue")
if result =~ /^Program received signal (.+?),/
signal = $1
if result =~ /^(Program|Thread .*) received signal (.+?),/
signal = $2
backtraces = execute("thread apply all bt full").strip
if backtraces.empty?
backtraces = execute("bt full").strip
Expand All @@ -166,12 +166,12 @@ def wait_until_exit
# the next machine instruction.
old_program_counter = program_counter
result = execute("stepi")
if result =~ /^Program received signal .+?,/
if result =~ /^(Program|Thread .*) received signal .+?,/
# Yes, it was fatal. Here we don't care whether the
# instruction caused a different signal. The last
# one is probably what we're interested in.
return ExitInfo.new(nil, signal, backtraces, snapshot)
elsif result =~ /^Program (terminated|exited)/ || result =~ /^Breakpoint .*? _exit/
elsif result =~ /^Program (terminated|exited)/ || result =~ /^Breakpoint .*? (__GI_)?_exit/
# Running the next instruction causes the program to terminate.
# Not sure what's going on but the previous signal and
# backtrace is probably what we're interested in.
Expand All @@ -192,7 +192,8 @@ def wait_until_exit
else
return ExitInfo.new(nil, signal, nil, snapshot)
end
elsif result =~ /^Breakpoint .*? _exit /
elsif result =~ /Breakpoint .*? (__GI_)?_exit (\(status=(\d+)\))?/
status_param = $3
backtraces = execute("thread apply all bt full").strip
if backtraces.empty?
backtraces = execute("bt full").strip
Expand All @@ -202,16 +203,18 @@ def wait_until_exit
# even though the process exited. Kernel bug? In any case,
# we put a timeout here so that we don't wait indefinitely.
result = execute("continue", 10)
if result =~ /^Program exited with code (\d+)\.$/
return ExitInfo.new($1.to_i, nil, backtraces, snapshot)
elsif result =~ /^Program exited normally/
if result =~ /^(Program|.*process .*) exited with code (\d+)/
return ExitInfo.new($2.to_i, nil, backtraces, snapshot)
elsif result =~ /^(Program|.*process .*) exited normally/
return ExitInfo.new(0, nil, backtraces, snapshot)
else
elsif status_param.nil? || status_param.empty?
return ExitInfo.new(nil, nil, backtraces, snapshot)
else
return ExitInfo.new(status_param.to_i, nil, backtraces, snapshot)
end
elsif result =~ /^Program exited with code (\d+)\.$/
return ExitInfo.new($1.to_i, nil, nil, nil)
elsif result =~ /^Program exited normally/
elsif result =~ /^(Program|.*process .*) exited with code (\d+)\.$/
return ExitInfo.new($2.to_i, nil, nil, nil)
elsif result =~ /^(Program|.*process .*) exited normally/
return ExitInfo.new(0, nil, nil, nil)
else
return ExitInfo.new(nil, nil, nil, nil)
Expand Down
9 changes: 5 additions & 4 deletions test/gdb_controller_spec.rb
Expand Up @@ -6,6 +6,7 @@
require 'spec_helper'
require 'crash_watch/utils'
require 'crash_watch/gdb_controller'
require 'shellwords'

describe CrashWatch::GdbController do
before :each do
Expand All @@ -21,7 +22,7 @@
end

def run_script_and_wait(code, snapshot_callback = nil, &block)
@process = IO.popen(%Q{ruby -e '#{code}'}, 'w')
@process = IO.popen(%Q{exec ruby -e #{Shellwords.escape code}}, 'w')
@gdb.attach(@process.pid)
thread = Thread.new do
sleep 0.1
Expand All @@ -32,7 +33,7 @@ def run_script_and_wait(code, snapshot_callback = nil, &block)
end
exit_info = @gdb.wait_until_exit(&snapshot_callback)
thread.join
return exit_info
exit_info
end

describe "#execute" do
Expand All @@ -47,13 +48,13 @@ def run_script_and_wait(code, snapshot_callback = nil, &block)
end

it "returns true if attaching worked" do
expect(@gdb.attach(@process.pid)).to be true
expect(@gdb.attach(@process.pid)).to be_truthy
end

it "returns false if the PID doesn't exist" do
Process.kill('KILL', @process.pid)
sleep 0.25
expect(@gdb.attach(@process.pid)).to be false
expect(@gdb.attach(@process.pid)).to be_falsey
end
end

Expand Down

0 comments on commit 8fc88f3

Please sign in to comment.