def wait_until_exit
execute("break _exit")
signal = nil
backtraces = nil
snapshot = nil
while true
result = execute("continue")
if result =~ /^Program received signal (.+?),/
signal = $1
backtraces = execute("thread apply all bt full").strip
if backtraces.empty?
backtraces = execute("bt full").strip
end
snapshot = yield(self) if block_given?
old_program_counter = program_counter
result = execute("stepi")
if result =~ /^Program received signal .+?,/
return ExitInfo.new(nil, signal, backtraces, snapshot)
elsif result =~ /^Program (terminated|exited)/ || result =~ /^Breakpoint .*? _exit/
return ExitInfo.new(nil, signal, backtraces, snapshot)
elsif old_program_counter == program_counter
raise "Unexpected GDB output: #{result}"
end
elsif result =~ /^Program terminated with signal (.+?),/
if $1 == signal
return ExitInfo.new(nil, signal, backtraces, snapshot)
else
return ExitInfo.new(nil, signal, nil, snapshot)
end
elsif result =~ /^Breakpoint .*? _exit /
backtraces = execute("thread apply all bt full").strip
if backtraces.empty?
backtraces = execute("bt full").strip
end
snapshot = yield(self) if block_given?
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/
return ExitInfo.new(0, nil, backtraces, snapshot)
else
return ExitInfo.new(nil, 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/
return ExitInfo.new(0, nil, nil, nil)
else
return ExitInfo.new(nil, nil, nil, nil)
end
end
end