gdbserver-support: Handle gdbserver start failures

As it happens we have a board that fails a gdb.base/gcore-relro.exp
test case reproducibly and moreover the case appears to trigger a
kernel bug making the it less than usable.  Specifically the board
remains responsive to some extent, however processes do not appear
to be able to successfully complete termination anymore and perhaps
more importantly further gdbserver processes can be started, but they
never reach the stage of listening on the RSP socket.

This change handles timeouts in gdbserver start properly, by throwing
a TCL error exception when gdbserver does not report listening on the
RSP socket in time.  This is then caught at the outer level and
reported, and 2 rather than 1 is returned so that the caller may tell
the failure to start gdbserver and other issues apart and act
accordingly (or do nothing).

I thought letting the exception unwind further on might be a good idea
for any test harnesses out there to break outright where a gdbserver
start error is silently ignored right now, however I figured out the
calls to gdbserver-support.exp are buried down too deep in the GDB test
suite for such a change to be made easily.  I think returning a distinct
return value is good enough (the API says "non-zero", so 2 is as good as
1) and we can always make the error harder in a later step if required.

With config/gdbserver.exp being used this change remains transparent
to the target board, the return value is passed up by gdb_reload and
the error exception unwinds through gdbserver_gdb_load and is caught
and handled by mi_gdb_target_load.  A call to perror is still made,
reporting the timeout, and in the case of mi_gdb_target_load the
procedure returns a value denoting unsuccessful completion.  An
unsuccessful completion of gdb_reload is already handled elsewhere.

An alternative gdbserver board configuration can interpret the return
value in its gdb_reload implementation and catch the error in
gdbserver_gdb_load in an attempt to recover a target board that has
gone astray, for example by rebooting the board somehow.  This has
proved effective with our failing board, that now completes the
remaining test cases with no further hiccups.

	* lib/gdbserver-support.exp (gdbserver_start): Throw an error
	exception on timeout.
	(gdbserver_run): Catch any `gdbserver_spawn' error exceptions.
	(gdbserver_start_extended): Catch any `gdbserver_start' error
	exceptions.
	(gdbserver_start_multi, mi_gdbserver_start_multi): Likewise.
	* lib/mi-support.exp (mi_gdb_target_load): Catch any
	`gdbserver_gdb_load' error exceptions.
This commit is contained in:
Maciej W. Rozycki 2014-09-09 16:17:38 +01:00
parent 2bdd10b78e
commit 09635af7cd
3 changed files with 36 additions and 6 deletions

View file

@ -1,3 +1,14 @@
2014-09-09 Maciej W. Rozycki <macro@codesourcery.com>
* lib/gdbserver-support.exp (gdbserver_start): Throw an error
exception on timeout.
(gdbserver_run): Catch any `gdbserver_spawn' error exceptions.
(gdbserver_start_extended): Catch any `gdbserver_start' error
exceptions.
(gdbserver_start_multi, mi_gdbserver_start_multi): Likewise.
* lib/mi-support.exp (mi_gdb_target_load): Catch any
`gdbserver_gdb_load' error exceptions.
2014-09-09 Maciej W. Rozycki <macro@codesourcery.com> 2014-09-09 Maciej W. Rozycki <macro@codesourcery.com>
* lib/gdbserver-support.exp (gdbserver_start): Set timeout to * lib/gdbserver-support.exp (gdbserver_start): Set timeout to

View file

@ -287,6 +287,9 @@ proc gdbserver_start { options arguments } {
continue continue
} }
} }
timeout {
error "Timeout waiting for gdbserver response."
}
} }
break break
} }
@ -326,7 +329,8 @@ proc gdbserver_spawn { child_args } {
} }
# Start a gdbserver process running HOST_EXEC and pass CHILD_ARGS # Start a gdbserver process running HOST_EXEC and pass CHILD_ARGS
# to it. Return 0 on success, or non-zero on failure. # to it. Return 0 on success, or non-zero on failure: 2 if gdbserver
# failed to start or 1 if we couldn't connect to it.
proc gdbserver_run { child_args } { proc gdbserver_run { child_args } {
global gdbserver_protocol global gdbserver_protocol
@ -347,7 +351,10 @@ proc gdbserver_run { child_args } {
} }
} }
set res [gdbserver_spawn $child_args] if { [catch { gdbserver_spawn $child_args } res] == 1 } {
perror $res
return 2
}
set gdbserver_protocol [lindex $res 0] set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1] set gdbserver_gdbport [lindex $res 1]
@ -377,7 +384,10 @@ proc gdbserver_start_extended { } {
global gdbserver_gdbport global gdbserver_gdbport
global use_gdb_stub global use_gdb_stub
set res [gdbserver_start "--multi" ""] if { [catch { gdbserver_start "--multi" "" } res] == 1 } {
perror $res
return 2
}
set gdbserver_protocol [lindex $res 0] set gdbserver_protocol [lindex $res 0]
if { [string first "extended-" $gdbserver_protocol] != 0} { if { [string first "extended-" $gdbserver_protocol] != 0} {
set gdbserver_protocol "extended-$gdbserver_protocol" set gdbserver_protocol "extended-$gdbserver_protocol"
@ -399,7 +409,10 @@ proc gdbserver_start_multi { } {
global gdbserver_protocol global gdbserver_protocol
global gdbserver_gdbport global gdbserver_gdbport
set res [gdbserver_start "--multi" ""] if { [catch { gdbserver_start "--multi" "" } res] == 1 } {
perror $res
return 2
}
set gdbserver_protocol [lindex $res 0] set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1] set gdbserver_gdbport [lindex $res 1]
@ -414,7 +427,10 @@ proc mi_gdbserver_start_multi { } {
global gdbserver_protocol global gdbserver_protocol
global gdbserver_gdbport global gdbserver_gdbport
set res [gdbserver_start "--multi" ""] if { [catch { gdbserver_start "--multi" "" } res] == 1 } {
perror $res
return 2
}
set gdbserver_protocol [lindex $res 0] set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1] set gdbserver_gdbport [lindex $res 1]

View file

@ -477,7 +477,10 @@ proc mi_gdb_target_load { } {
if { [info procs gdbserver_gdb_load] != "" } { if { [info procs gdbserver_gdb_load] != "" } {
mi_gdb_test "kill" ".*" "" mi_gdb_test "kill" ".*" ""
set res [gdbserver_gdb_load] if { [catch gdbserver_gdb_load res] == 1 } {
perror $res
return -1
}
set protocol [lindex $res 0] set protocol [lindex $res 0]
set gdbport [lindex $res 1] set gdbport [lindex $res 1]