<rdar://problem/11672978> Fixing an issue where an ObjC object might come out without a description because the expression used to obtain it would timeout before running to completion

llvm-svn: 160326
This commit is contained in:
Enrico Granata 2012-07-16 23:10:35 +00:00
parent 482fb19fd5
commit 3372f581eb
10 changed files with 54 additions and 18 deletions

View File

@ -132,6 +132,10 @@ public:
/// A pointer to direct at the persistent variable in which the
/// expression's result is stored.
///
/// @param[in] single_thread_timeout_usec
/// The amount of time (in usec) that we are willing to wait for this
/// expression to complete, before assuming that we are blocked and giving up
///
/// @return
/// A Process::Execution results value.
//------------------------------------------------------------------
@ -140,7 +144,8 @@ public:
ExecutionContext &exe_ctx,
bool discard_on_error,
ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
lldb::ClangExpressionVariableSP &result,
uint32_t single_thread_timeout_usec = 500000);
ThreadPlan *
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
@ -309,6 +314,10 @@ public:
/// @param[in/out] result_valobj_sp
/// If execution is successful, the result valobj is placed here.
///
/// @param[in] single_thread_timeout_usec
/// The amount of time (in usec) that we are willing to wait for this
/// expression to complete, before assuming that we are blocked and giving up
///
/// @result
/// A Process::ExecutionResults value. eExecutionCompleted for success.
//------------------------------------------------------------------
@ -320,7 +329,8 @@ public:
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
lldb::ValueObjectSP &result_valobj_sp,
uint32_t single_thread_timeout_usec = 500000);
static ExecutionResults
EvaluateWithError (ExecutionContext &exe_ctx,
@ -331,7 +341,8 @@ public:
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error);
Error &error,
uint32_t single_thread_timeout_usec = 500000);
static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
private:

View File

@ -898,7 +898,8 @@ public:
bool unwind_on_error,
bool keep_in_memory,
lldb::DynamicValueType use_dynamic,
lldb::ValueObjectSP &result_valobj_sp);
lldb::ValueObjectSP &result_valobj_sp,
uint32_t single_thread_timeout_usec = 500000);
ClangPersistentVariables &
GetPersistentVariables()

View File

@ -305,7 +305,8 @@ CommandObjectExpression::EvaluateExpression
m_command_options.unwind_on_error,
keep_in_memory,
use_dynamic,
result_valobj_sp);
result_valobj_sp,
0 /* no timeout */);
if (exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error)
{

View File

@ -1206,7 +1206,8 @@ protected:
unwind_on_error,
keep_in_memory,
eNoDynamicValues,
valobj_sp);
valobj_sp,
0 /* no timeout */);
if (expr_result != eExecutionCompleted) {
result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());

View File

@ -542,7 +542,8 @@ ClangUserExpression::Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
bool discard_on_error,
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result)
lldb::ClangExpressionVariableSP &result,
uint32_t single_thread_timeout_usec)
{
// The expression log is quite verbose, and if you're just tracking the execution of the
// expression, it's quite convenient to have these logs come out with the STEP log as well.
@ -578,8 +579,6 @@ ClangUserExpression::Execute (Stream &error_stream,
call_plan_sp->SetPrivate(true);
uint32_t single_thread_timeout_usec = 500000;
if (log)
log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
@ -648,10 +647,11 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp)
lldb::ValueObjectSP &result_valobj_sp,
uint32_t single_thread_timeout_usec)
{
Error error;
return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error, single_thread_timeout_usec);
}
ExecutionResults
@ -663,7 +663,8 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error)
Error &error,
uint32_t single_thread_timeout_usec)
{
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@ -738,7 +739,8 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
exe_ctx,
discard_on_error,
user_expression_sp,
expr_result);
expr_result,
single_thread_timeout_usec);
if (execution_results != eExecutionCompleted)
{

View File

@ -1162,7 +1162,8 @@ CommandInterpreter::PreprocessCommand (std::string &command)
unwind_on_error,
keep_in_memory,
eNoDynamicValues,
expr_result_valobj_sp);
expr_result_valobj_sp,
0 /* no timeout */);
if (expr_result == eExecutionCompleted)
{
Scalar scalar;

View File

@ -142,7 +142,7 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon
&wrapper_struct_addr,
error_stream,
stop_others,
100000,
0 /* no timeout */,
try_all_threads,
unwind_on_error,
ret);

View File

@ -4228,11 +4228,27 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (single_thread_timeout_usec != 0)
{
// we have a > 0 timeout, let us set it so that we stop after the deadline
real_timeout = TimeValue::Now();
real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
timeout_ptr = &real_timeout;
}
else if (first_timeout)
{
// if we are willing to wait "forever" we still need to have an initial timeout
// this timeout is going to induce all threads to run when hit. we do this so that
// we can avoid ending locked up because of multithreaded contention issues
real_timeout = TimeValue::Now();
real_timeout.OffsetWithNanoSeconds(500000000UL);
timeout_ptr = &real_timeout;
}
else
{
timeout_ptr = NULL; // if we are in a no-timeout scenario, then we only need a fake timeout the first time through
// at this point in the code, all threads will be running so we are willing to wait forever, and do not
// need a timeout
}
}
else
{

View File

@ -520,7 +520,8 @@ public:
wp_sp->GetConditionText(),
NULL,
result_value_sp,
error);
error,
500000);
if (result_code == eExecutionCompleted)
{
if (result_value_sp)

View File

@ -1652,7 +1652,8 @@ Target::EvaluateExpression
bool unwind_on_error,
bool keep_in_memory,
lldb::DynamicValueType use_dynamic,
lldb::ValueObjectSP &result_valobj_sp
lldb::ValueObjectSP &result_valobj_sp,
uint32_t single_thread_timeout_usec
)
{
ExecutionResults execution_results = eExecutionSetupError;
@ -1781,7 +1782,8 @@ Target::EvaluateExpression
unwind_on_error,
expr_cstr,
prefix,
result_valobj_sp);
result_valobj_sp,
single_thread_timeout_usec);
}
}