@ -218,6 +218,27 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
value ) ;
}
/* This boolean tells GDB what to do if an inferior function, called from
GDB , times out . If true , GDB unwinds the stack and restores the context
to what it was before the call . When false , GDB leaves the thread as it
is at the point of the timeout .
The default is to stop in the frame where the timeout occurred . */
static bool unwind_on_timeout_p = false ;
/* Implement 'show unwind-on-timeout'. */
static void
show_unwind_on_timeout_p ( struct ui_file * file , int from_tty ,
struct cmd_list_element * c , const char * value )
{
gdb_printf ( file ,
_ ( " Unwinding of stack if a timeout occurs "
" while in a call dummy is %s. \n " ) ,
value ) ;
}
/* Perform the standard coercions that are specified
for arguments to be passed to C , Ada or Fortran functions .
@ -574,6 +595,16 @@ struct call_thread_fsm : public thread_fsm
bool should_stop ( struct thread_info * thread ) override ;
bool should_notify_stop ( ) override ;
/* Record that this thread timed out while performing an infcall. */
void timed_out ( )
{
m_timed_out = true ;
}
private :
/* Set true if the thread timed out while performing an infcall. */
bool m_timed_out = false ;
} ;
/* Allocate a new call_thread_fsm object. */
@ -649,7 +680,8 @@ call_thread_fsm::should_notify_stop ()
infcall_debug_printf ( " inferior call didn't complete fully " ) ;
if ( stopped_by_random_signal & & unwind_on_signal_p )
if ( ( stopped_by_random_signal & & unwind_on_signal_p )
| | ( m_timed_out & & unwind_on_timeout_p ) )
{
infcall_debug_printf ( " unwind-on-signal is on, don't notify " ) ;
return false ;
@ -742,6 +774,9 @@ private:
infcall_debug_printf ( " Stopping thread %s " ,
m_thread - > ptid . to_string ( ) . c_str ( ) ) ;
call_thread_fsm * fsm
= gdb : : checked_static_cast < call_thread_fsm * > ( m_thread - > thread_fsm ( ) ) ;
fsm - > timed_out ( ) ;
target_stop ( m_thread - > ptid ) ;
}
} ;
@ -1749,14 +1784,27 @@ When the function is done executing, GDB will silently stop."),
/* A timeout results in a signal being sent to the inferior. */
gdb_assert ( stopped_by_random_signal ) ;
/* Indentation is weird here. A later patch is going to move the
following block into an if / else , so I ' m leaving the indentation
here to minimise the later patch .
if ( unwind_on_timeout_p )
{
/* The user wants the context restored. */
/* We must get back to the frame we were before the
dummy call . */
dummy_frame_pop ( dummy_id , call_thread . get ( ) ) ;
Also , the error message used below refers to ' set
unwind - on - timeout ' which doesn ' t exist yet . This will be added
in a later commit , I ' m leaving this in for now to minimise the
churn caused by the commit that adds unwind - on - timeout . */
/* We also need to restore inferior status to that before the
dummy call . */
restore_infcall_control_state ( inf_status . release ( ) ) ;
error ( _ ( " \
The program being debugged timed out while in a function called from GDB . \ n \
GDB has restored the context to what it was before the call . \ n \
To change this behavior use \ " set unwind-on-timeout off \" . \n \
Evaluation of the expression containing the function \ n \
( % s ) will be abandoned . " ),
name . c_str ( ) ) ;
}
else
{
/* The user wants to stay in the frame where we stopped
( default ) . Discard inferior status , we ' re not at the same
@ -1882,6 +1930,20 @@ The default is to unwind the frame."),
show_unwind_on_terminating_exception_p ,
& setlist , & showlist ) ;
add_setshow_boolean_cmd ( " unwind-on-timeout " , no_class ,
& unwind_on_timeout_p , _ ( " \
Set unwinding of stack if a timeout occurs while in a call dummy . " ), _( " \
Show unwinding of stack if a timeout occurs while in a call dummy . " ),
_ ( " \
The unwind on timeout flag lets the user determine what gdb should do if \ n \
gdb times out while in a function called from gdb . If set , gdb unwinds \ n \
the stack and restores the context to what it was before the call . If \ n \
unset , gdb leaves the inferior in the frame where the timeout occurred . \ n \
The default is to stop in the frame where the timeout occurred . " ),
NULL ,
show_unwind_on_timeout_p ,
& setlist , & showlist ) ;
add_setshow_uinteger_cmd ( " direct-call-timeout " , no_class ,
& direct_call_timeout , _ ( " \
Set the timeout , for direct calls to inferior function calls . " ), _( " \