diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h index 58b45ebd793af..6a4a39c4db314 100644 --- a/lldb/include/lldb/API/SBError.h +++ b/lldb/include/lldb/API/SBError.h @@ -87,6 +87,7 @@ class LLDB_API SBError { friend class SBDebugger; friend class SBFile; friend class SBFormat; + friend class SBFrame; friend class SBHostOS; friend class SBPlatform; friend class SBProcess; diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index 3635ee5a537ad..08de0605b3240 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -233,6 +233,10 @@ class LLDB_API SBFrame { void SetFrameSP(const lldb::StackFrameSP &lldb_object_sp); + /// Return an SBValue containing an error message that warns the process is + /// not currently stopped. + static SBValue CreateProcessIsRunningExprEvalError(); + lldb::ExecutionContextRefSP m_opaque_sp; }; diff --git a/lldb/include/lldb/Host/ProcessRunLock.h b/lldb/include/lldb/Host/ProcessRunLock.h index 94683673024d5..27d10942ddb4c 100644 --- a/lldb/include/lldb/Host/ProcessRunLock.h +++ b/lldb/include/lldb/Host/ProcessRunLock.h @@ -41,9 +41,22 @@ class ProcessRunLock { class ProcessRunLocker { public: ProcessRunLocker() = default; + ProcessRunLocker(ProcessRunLocker &&other) : m_lock(other.m_lock) { + other.m_lock = nullptr; + } + ProcessRunLocker &operator=(ProcessRunLocker &&other) { + if (this != &other) { + Unlock(); + m_lock = other.m_lock; + other.m_lock = nullptr; + } + return *this; + } ~ProcessRunLocker() { Unlock(); } + bool IsLocked() const { return m_lock; } + // Try to lock the read lock, but only do so if there are no writers. bool TryLock(ProcessRunLock *lock) { if (m_lock) { diff --git a/lldb/include/lldb/Target/ExecutionContext.h b/lldb/include/lldb/Target/ExecutionContext.h index aebd0d5308e72..a0b064a51cec4 100644 --- a/lldb/include/lldb/Target/ExecutionContext.h +++ b/lldb/include/lldb/Target/ExecutionContext.h @@ -11,6 +11,7 @@ #include +#include "lldb/Host/ProcessRunLock.h" #include "lldb/Target/StackID.h" #include "lldb/lldb-private.h" @@ -315,14 +316,6 @@ class ExecutionContext { ExecutionContext(const ExecutionContextRef *exe_ctx_ref, bool thread_and_frame_only_if_stopped = false); - // These two variants take in a locker, and grab the target, lock the API - // mutex into locker, then fill in the rest of the shared pointers. - ExecutionContext(const ExecutionContextRef &exe_ctx_ref, - std::unique_lock &locker) - : ExecutionContext(&exe_ctx_ref, locker) {} - - ExecutionContext(const ExecutionContextRef *exe_ctx_ref, - std::unique_lock &locker); // Create execution contexts from execution context scopes ExecutionContext(ExecutionContextScope *exe_scope); ExecutionContext(ExecutionContextScope &exe_scope); @@ -566,6 +559,53 @@ class ExecutionContext { lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread. }; +/// A wrapper class representing an execution context with non-null Target +/// and Process pointers, a locked API mutex and a locked ProcessRunLock. +/// The locks are private by design: to unlock them, destroy the +/// StoppedExecutionContext. +struct StoppedExecutionContext : ExecutionContext { + StoppedExecutionContext(lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::ThreadSP &thread_sp, + lldb::StackFrameSP &frame_sp, + std::unique_lock api_lock, + ProcessRunLock::ProcessRunLocker stop_locker) + : m_api_lock(std::move(api_lock)), m_stop_locker(std::move(stop_locker)) { + assert(target_sp); + assert(process_sp); + assert(m_api_lock.owns_lock()); + assert(m_stop_locker.IsLocked()); + SetTargetSP(target_sp); + SetProcessSP(process_sp); + SetThreadSP(thread_sp); + SetFrameSP(frame_sp); + } + + /// Transfers ownership of the locks from `other` to `this`, making `other` + /// unusable. + StoppedExecutionContext(StoppedExecutionContext &&other) + : StoppedExecutionContext(other.m_target_sp, other.m_process_sp, + other.m_thread_sp, other.m_frame_sp, + std::move(other.m_api_lock), + std::move(other.m_stop_locker)) { + other.Clear(); + } + + /// Clears this context, unlocking the ProcessRunLock and returning the + /// locked API lock. Like after a move operation, this object is no longer + /// usable. + [[nodiscard]] std::unique_lock Destroy(); + +private: + std::unique_lock m_api_lock; + ProcessRunLock::ProcessRunLocker m_stop_locker; +}; + +llvm::Expected +GetStoppedExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr); +llvm::Expected +GetStoppedExecutionContext(const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr); + } // namespace lldb_private #endif // LLDB_TARGET_EXECUTIONCONTEXT_H diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 5b69cf1ee2641..b12cfceacd75d 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -97,226 +97,176 @@ bool SBFrame::IsValid() const { } SBFrame::operator bool() const { LLDB_INSTRUMENT_VA(this); - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) - return GetFrameSP().get() != nullptr; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } - // Without a target & process we can't have a valid stack frame. - return false; + return GetFrameSP().get() != nullptr; } SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const { LLDB_INSTRUMENT_VA(this, resolve_scope); SBSymbolContext sb_sym_ctx; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - SymbolContextItem scope = static_cast(resolve_scope); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) - sb_sym_ctx = frame->GetSymbolContext(scope); - } + + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_sym_ctx; } + SymbolContextItem scope = static_cast(resolve_scope); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + sb_sym_ctx = frame->GetSymbolContext(scope); + return sb_sym_ctx; } SBModule SBFrame::GetModule() const { LLDB_INSTRUMENT_VA(this); - SBModule sb_module; - ModuleSP module_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp; - sb_module.SetSP(module_sp); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBModule(); } + ModuleSP module_sp; + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBModule(); + + SBModule sb_module; + module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp; + sb_module.SetSP(module_sp); return sb_module; } SBCompileUnit SBFrame::GetCompileUnit() const { LLDB_INSTRUMENT_VA(this); - SBCompileUnit sb_comp_unit; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_comp_unit.reset( - frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBCompileUnit(); } - return sb_comp_unit; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBCompileUnit( + frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit); + return SBCompileUnit(); } SBFunction SBFrame::GetFunction() const { LLDB_INSTRUMENT_VA(this); - SBFunction sb_function; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_function.reset( - frame->GetSymbolContext(eSymbolContextFunction).function); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFunction(); } - return sb_function; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBFunction(frame->GetSymbolContext(eSymbolContextFunction).function); + return SBFunction(); } SBSymbol SBFrame::GetSymbol() const { LLDB_INSTRUMENT_VA(this); - SBSymbol sb_symbol; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_symbol.reset(frame->GetSymbolContext(eSymbolContextSymbol).symbol); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBSymbol(); } - return sb_symbol; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBSymbol(frame->GetSymbolContext(eSymbolContextSymbol).symbol); + return SBSymbol(); } SBBlock SBFrame::GetBlock() const { LLDB_INSTRUMENT_VA(this); - SBBlock sb_block; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_block.SetPtr(frame->GetSymbolContext(eSymbolContextBlock).block); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBBlock(); } - return sb_block; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBBlock(frame->GetSymbolContext(eSymbolContextBlock).block); + return SBBlock(); } SBBlock SBFrame::GetFrameBlock() const { LLDB_INSTRUMENT_VA(this); - SBBlock sb_block; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_block.SetPtr(frame->GetFrameBlock()); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBBlock(); } - return sb_block; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBBlock(frame->GetFrameBlock()); + return SBBlock(); } SBLineEntry SBFrame::GetLineEntry() const { LLDB_INSTRUMENT_VA(this); - SBLineEntry sb_line_entry; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_line_entry.SetLineEntry( - frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBLineEntry(); } - return sb_line_entry; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBLineEntry( + &frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); + return SBLineEntry(); } uint32_t SBFrame::GetFrameID() const { LLDB_INSTRUMENT_VA(this); - uint32_t frame_idx = UINT32_MAX; - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + constexpr uint32_t error_frame_idx = UINT32_MAX; - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - frame_idx = frame->GetFrameIndex(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error_frame_idx; + } - return frame_idx; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFrameIndex(); + return error_frame_idx; } lldb::addr_t SBFrame::GetCFA() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->GetStackID().GetCallFrameAddress(); return LLDB_INVALID_ADDRESS; } @@ -325,114 +275,86 @@ addr_t SBFrame::GetPC() const { LLDB_INSTRUMENT_VA(this); addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress( - target, AddressClass::eCode); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return addr; } + Target *target = exe_ctx->GetTargetPtr(); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFrameCodeAddress().GetOpcodeLoadAddress( + target, AddressClass::eCode); + return addr; } bool SBFrame::SetPC(addr_t new_pc) { LLDB_INSTRUMENT_VA(this, new_pc); - bool ret_val = false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - ret_val = reg_ctx_sp->SetPC(new_pc); - } - } - } + constexpr bool error_ret_val = false; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error_ret_val; } - return ret_val; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->SetPC(new_pc); + + return error_ret_val; } addr_t SBFrame::GetSP() const { LLDB_INSTRUMENT_VA(this); - addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - addr = reg_ctx_sp->GetSP(); - } - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; } - return addr; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->GetSP(); + + return LLDB_INVALID_ADDRESS; } addr_t SBFrame::GetFP() const { LLDB_INSTRUMENT_VA(this); - addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - addr = reg_ctx_sp->GetFP(); - } - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; } - return addr; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->GetFP(); + + return LLDB_INVALID_ADDRESS; } SBAddress SBFrame::GetPCAddress() const { LLDB_INSTRUMENT_VA(this); - SBAddress sb_addr; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_addr.SetAddress(frame->GetFrameCodeAddress()); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBAddress(); } - return sb_addr; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBAddress(frame->GetFrameCodeAddress()); + return SBAddress(); } void SBFrame::Clear() { @@ -445,12 +367,14 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) { LLDB_INSTRUMENT_VA(this, var_path); SBValue sb_value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); sb_value = GetValueForVariablePath(var_path, use_dynamic); @@ -467,27 +391,22 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, return sb_value; } - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - VariableSP var_sp; - Status error; - ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( - var_path, eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, - var_sp, error)); - sb_value.SetSP(value_sp, use_dynamic); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; + } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) { + VariableSP var_sp; + Status error; + ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( + var_path, eNoDynamicValues, + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, + var_sp, error)); + sb_value.SetSP(value_sp, use_dynamic); } return sb_value; } @@ -495,18 +414,19 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, SBValue SBFrame::FindVariable(const char *name) { LLDB_INSTRUMENT_VA(this, name); - SBValue value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); - value = FindVariable(name, use_dynamic); + return FindVariable(name, use_dynamic); } - return value; + return SBValue(); } SBValue SBFrame::FindVariable(const char *name, @@ -520,26 +440,17 @@ SBValue SBFrame::FindVariable(const char *name, return sb_value; } - ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - value_sp = frame->FindVariable(ConstString(name)); - - if (value_sp) - sb_value.SetSP(value_sp, use_dynamic); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; } + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (ValueObjectSP value_sp = frame->FindVariable(ConstString(name))) + sb_value.SetSP(value_sp, use_dynamic); + return sb_value; } @@ -547,12 +458,14 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type) { LLDB_INSTRUMENT_VA(this, name, value_type); SBValue value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); value = FindValue(name, value_type, use_dynamic); @@ -571,17 +484,17 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type, } ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value_sp; + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { VariableList variable_list; switch (value_type) { @@ -698,10 +611,14 @@ bool SBFrame::operator!=(const SBFrame &rhs) const { SBThread SBFrame::GetThread() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBThread(); + } - ThreadSP thread_sp(exe_ctx.GetThreadSP()); + ThreadSP thread_sp(exe_ctx->GetThreadSP()); SBThread sb_thread(thread_sp); return sb_thread; @@ -710,19 +627,16 @@ SBThread SBFrame::GetThread() const { const char *SBFrame::Disassemble() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (!target || !process) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; - - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (auto *frame = exe_ctx.GetFramePtr()) - return ConstString(frame->Disassemble()).GetCString(); } + if (auto *frame = exe_ctx->GetFramePtr()) + return ConstString(frame->Disassemble()).GetCString(); + return nullptr; } @@ -731,12 +645,15 @@ SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics, LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value_list; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { + Target *target = exe_ctx->GetTargetPtr(); lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); const bool include_runtime_support_values = @@ -761,12 +678,16 @@ lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals, LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only, use_dynamic); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } - Target *target = exe_ctx.GetTargetPtr(); + Target *target = exe_ctx->GetTargetPtr(); const bool include_runtime_support_values = - target ? target->GetDisplayRuntimeSupportValues() : false; + target->GetDisplayRuntimeSupportValues(); SBVariablesOptions options; options.SetIncludeArguments(arguments); options.SetIncludeLocals(locals); @@ -781,30 +702,26 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { LLDB_INSTRUMENT_VA(this, options); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - - const bool statics = options.GetIncludeStatics(); - const bool arguments = options.GetIncludeArguments(); - const bool recognized_arguments = - options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP())); - const bool locals = options.GetIncludeLocals(); - const bool in_scope_only = options.GetInScopeOnly(); - const bool include_runtime_support_values = - options.GetIncludeRuntimeSupportValues(); - const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } else { + const bool statics = options.GetIncludeStatics(); + const bool arguments = options.GetIncludeArguments(); + const bool recognized_arguments = + options.GetIncludeRecognizedArguments(SBTarget(exe_ctx->GetTargetSP())); + const bool locals = options.GetIncludeLocals(); + const bool in_scope_only = options.GetInScopeOnly(); + const bool include_runtime_support_values = + options.GetIncludeRuntimeSupportValues(); + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - std::set variable_set; - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + std::set variable_set; + Process *process = exe_ctx->GetProcessPtr(); + if (process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { Debugger &dbg = process->GetTarget().GetDebugger(); VariableList *variable_list = nullptr; Status var_error; @@ -892,17 +809,16 @@ SBValueList SBFrame::GetRegisters() { LLDB_INSTRUMENT_VA(this); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); @@ -923,17 +839,16 @@ SBValue SBFrame::FindRegister(const char *name) { SBValue result; ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { if (const RegisterInfo *reg_info = @@ -953,12 +868,11 @@ SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, SBStream &output) { Stream &strm = output.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); SBError error; if (!format) { @@ -966,16 +880,9 @@ SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, return error; } - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame && - frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) { - return error; - } - } - } + if (StackFrame *frame = exe_ctx->GetFramePtr(); + frame && frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) + return error; error.SetErrorStringWithFormat( "It was not possible to generate a frame " "description with the given format string '%s'", @@ -988,23 +895,16 @@ bool SBFrame::GetDescription(SBStream &description) { Stream &strm = description.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - frame->DumpUsingSettingsFormat(&strm); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + strm.PutCString("Error: process is not stopped."); + return true; + } - } else - strm.PutCString("No value"); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + frame->DumpUsingSettingsFormat(&strm); return true; } @@ -1012,22 +912,24 @@ bool SBFrame::GetDescription(SBStream &description) { SBValue SBFrame::EvaluateExpression(const char *expr) { LLDB_INSTRUMENT_VA(this, expr); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); SBExpressionOptions options; - if (frame && target) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue(); options.SetFetchDynamicValue(fetch_dynamic_value); } options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); @@ -1043,14 +945,16 @@ SBFrame::EvaluateExpression(const char *expr, options.SetFetchDynamicValue(fetch_dynamic_value); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } + + StackFrame *frame = exe_ctx->GetFramePtr(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); @@ -1063,23 +967,35 @@ SBValue SBFrame::EvaluateExpression(const char *expr, LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value, unwind_on_error); SBExpressionOptions options; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } options.SetFetchDynamicValue(fetch_dynamic_value); options.SetUnwindOnError(unwind_on_error); options.SetIgnoreBreakpoints(true); - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + StackFrame *frame = exe_ctx->GetFramePtr(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); return EvaluateExpression(expr, options); } +lldb::SBValue SBFrame::CreateProcessIsRunningExprEvalError() { + auto error = Status::FromErrorString("can't evaluate expressions when the " + "process is running."); + ValueObjectSP expr_value_sp = + ValueObjectConstResult::Create(nullptr, std::move(error)); + SBValue expr_result; + expr_result.SetSP(expr_value_sp, false); + return expr_result; +} + lldb::SBValue SBFrame::EvaluateExpression(const char *expr, const SBExpressionOptions &options) { LLDB_INSTRUMENT_VA(this, expr, options); @@ -1094,18 +1010,16 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, ValueObjectSP expr_value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + expr_result = CreateProcessIsRunningExprEvalError(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { std::unique_ptr stack_trace; if (target->GetDisplayExpressionsInCrashlogs()) { StreamString frame_description; @@ -1121,17 +1035,11 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); } } else { - Status error; - error = Status::FromErrorString("can't evaluate expressions when the " - "process is running."); - expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error)); - expr_result.SetSP(expr_value_sp, false); - } - } else { Status error; error = Status::FromErrorString("sbframe object is not valid."); expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error)); expr_result.SetSP(expr_value_sp, false); + } } if (expr_result.GetError().Success()) @@ -1152,9 +1060,13 @@ SBStructuredData SBFrame::GetLanguageSpecificData() const { LLDB_INSTRUMENT_VA(this); SBStructuredData sb_data; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - StackFrame *frame = exe_ctx.GetFramePtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_data; + } + StackFrame *frame = exe_ctx->GetFramePtr(); if (!frame) return sb_data; @@ -1172,20 +1084,15 @@ bool SBFrame::IsInlined() { bool SBFrame::IsInlined() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->IsInlined(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->IsInlined(); return false; } @@ -1198,10 +1105,14 @@ bool SBFrame::IsArtificial() { bool SBFrame::IsArtificial() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (StackFrame *frame = exe_ctx.GetFramePtr()) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->IsArtificial(); return false; @@ -1210,10 +1121,14 @@ bool SBFrame::IsArtificial() const { bool SBFrame::IsHidden() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (StackFrame *frame = exe_ctx.GetFramePtr()) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->IsHidden(); return false; @@ -1228,63 +1143,44 @@ const char *SBFrame::GetFunctionName() { lldb::LanguageType SBFrame::GuessLanguage() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - return frame->GuessLanguage().AsLanguageType(); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return eLanguageTypeUnknown; } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GuessLanguage().AsLanguageType(); return eLanguageTypeUnknown; } const char *SBFrame::GetFunctionName() const { LLDB_INSTRUMENT_VA(this); - const char *name = nullptr; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->GetFunctionName(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return nullptr; } - return name; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFunctionName(); + return nullptr; } const char *SBFrame::GetDisplayFunctionName() { LLDB_INSTRUMENT_VA(this); - const char *name = nullptr; - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->GetDisplayFunctionName(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return nullptr; } - return name; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetDisplayFunctionName(); + return nullptr; } diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 74bc66c4f16f1..b07611d388fb6 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -90,16 +90,17 @@ lldb::SBQueue SBThread::GetQueue() const { SBQueue sb_queue; QueueSP queue_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - queue_sp = exe_ctx.GetThreadPtr()->GetQueue(); - if (queue_sp) { - sb_queue.SetQueue(queue_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBQueue(); + } + + if (exe_ctx->HasThreadScope()) { + queue_sp = exe_ctx->GetThreadPtr()->GetQueue(); + if (queue_sp) { + sb_queue.SetQueue(queue_sp); } } @@ -112,19 +113,17 @@ bool SBThread::IsValid() const { } SBThread::operator bool() const { LLDB_INSTRUMENT_VA(this); + if (!m_opaque_sp) + return false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) - return m_opaque_sp->GetThreadSP().get() != nullptr; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } - // Without a valid target & process, this thread can't be valid. - return false; + + return m_opaque_sp->GetThreadSP().get() != nullptr; } void SBThread::Clear() { @@ -137,29 +136,27 @@ StopReason SBThread::GetStopReason() { LLDB_INSTRUMENT_VA(this); StopReason reason = eStopReasonInvalid; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - return exe_ctx.GetThreadPtr()->GetStopReason(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return reason; } + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetStopReason(); + return reason; } size_t SBThread::GetStopReasonDataCount() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo(); if (stop_info_sp) { StopReason reason = stop_info_sp->GetStopReason(); switch (reason) { @@ -179,7 +176,7 @@ size_t SBThread::GetStopReasonDataCount() { case eStopReasonBreakpoint: { break_id_t site_id = stop_info_sp->GetValue(); lldb::BreakpointSiteSP bp_site_sp( - exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID( + exe_ctx->GetProcessPtr()->GetBreakpointSiteList().FindByID( site_id)); if (bp_site_sp) return bp_site_sp->GetNumberOfConstituents() * 2; @@ -207,6 +204,9 @@ size_t SBThread::GetStopReasonDataCount() { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } return 0; } @@ -214,13 +214,11 @@ size_t SBThread::GetStopReasonDataCount() { uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); StopInfoSP stop_info_sp = thread->GetStopInfo(); if (stop_info_sp) { StopReason reason = stop_info_sp->GetStopReason(); @@ -241,7 +239,7 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { case eStopReasonBreakpoint: { break_id_t site_id = stop_info_sp->GetValue(); lldb::BreakpointSiteSP bp_site_sp( - exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID( + exe_ctx->GetProcessPtr()->GetBreakpointSiteList().FindByID( site_id)); if (bp_site_sp) { uint32_t bp_index = idx / 2; @@ -280,6 +278,9 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } return 0; } @@ -289,13 +290,17 @@ bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) { Stream &strm = stream.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (!exe_ctx.HasThreadScope()) + if (!exe_ctx->HasThreadScope()) return false; - StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo(); + StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo(); StructuredData::ObjectSP info = stop_info->GetExtendedInfo(); if (!info) return false; @@ -311,15 +316,19 @@ SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) { SBThreadCollection threads; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBThreadCollection(); + } - if (!exe_ctx.HasThreadScope()) + if (!exe_ctx->HasThreadScope()) return SBThreadCollection(); - ProcessSP process_sp = exe_ctx.GetProcessSP(); + ProcessSP process_sp = exe_ctx->GetProcessSP(); - StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo(); + StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo(); StructuredData::ObjectSP info = stop_info->GetExtendedInfo(); if (!info) return threads; @@ -332,20 +341,20 @@ SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) { size_t SBThread::GetStopDescription(char *dst, size_t dst_len) { LLDB_INSTRUMENT_VA(this, dst, dst_len); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - if (dst) *dst = 0; - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return 0; + } - Process::StopLocker stop_locker; - if (!stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) + if (!exe_ctx->HasThreadScope()) return 0; - std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription(); + std::string thread_stop_desc = exe_ctx->GetThreadPtr()->GetStopDescription(); if (thread_stop_desc.empty()) return 0; @@ -361,16 +370,17 @@ SBValue SBThread::GetStopReturnValue() { LLDB_INSTRUMENT_VA(this); ValueObjectSP return_valobj_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo(); - if (stop_info_sp) { - return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp); - } + if (exe_ctx->HasThreadScope()) { + StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo(); + if (stop_info_sp) { + return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp); } } @@ -402,47 +412,48 @@ uint32_t SBThread::GetIndexID() const { const char *SBThread::GetName() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; + } - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) - return ConstString(exe_ctx.GetThreadPtr()->GetName()).GetCString(); + if (!exe_ctx->HasThreadScope()) + return nullptr; - return nullptr; + return ConstString(exe_ctx->GetThreadPtr()->GetName()).GetCString(); } const char *SBThread::GetQueueName() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; + } - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) - return ConstString(exe_ctx.GetThreadPtr()->GetQueueName()).GetCString(); + if (!exe_ctx->HasThreadScope()) + return nullptr; - return nullptr; + return ConstString(exe_ctx->GetThreadPtr()->GetQueueName()).GetCString(); } lldb::queue_id_t SBThread::GetQueueID() const { LLDB_INSTRUMENT_VA(this); queue_id_t id = LLDB_INVALID_QUEUE_ID; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return id; + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - id = exe_ctx.GetThreadPtr()->GetQueueID(); - } + if (exe_ctx->HasThreadScope()) { + id = exe_ctx->GetThreadPtr()->GetQueueID(); } return id; @@ -452,13 +463,11 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { LLDB_INSTRUMENT_VA(this, path, strm); bool success = false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo(); if (info_root_sp) { StructuredData::ObjectSP node = @@ -490,16 +499,16 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return success; } return success; } -static Status ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { - Process *process = exe_ctx.GetProcessPtr(); - if (!process) - return Status::FromErrorString("No process in SBThread::ResumeNewPlan"); - +static Status ResumeNewPlan(StoppedExecutionContext exe_ctx, + ThreadPlan *new_plan) { Thread *thread = exe_ctx.GetThreadPtr(); if (!thread) return Status::FromErrorString("No thread in SBThread::ResumeNewPlan"); @@ -512,8 +521,11 @@ static Status ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { } // Why do we need to set the current thread by ID here??? + Process *process = exe_ctx.GetProcessPtr(); process->GetThreadList().SetSelectedThreadByID(thread->GetID()); + // Release the run lock but keep the API lock. + std::unique_lock api_lock = exe_ctx.Destroy(); if (process->GetTarget().GetDebugger().GetAsyncExecution()) return process->Resume(); return process->ResumeSynchronous(nullptr); @@ -529,15 +541,19 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads) { void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) { LLDB_INSTRUMENT_VA(this, stop_other_threads, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); bool abort_other_plans = false; StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); @@ -555,7 +571,7 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) { true, abort_other_plans, stop_other_threads, new_plan_status); } } - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); } void SBThread::StepInto(lldb::RunMode stop_other_threads) { @@ -576,17 +592,21 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line, SBError &error, lldb::RunMode stop_other_threads) { LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } bool abort_other_plans = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); ThreadPlanSP new_plan_sp; Status new_plan_status; @@ -618,7 +638,7 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line, } if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -633,10 +653,14 @@ void SBThread::StepOut() { void SBThread::StepOut(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } @@ -644,7 +668,7 @@ void SBThread::StepOut(SBError &error) { bool abort_other_plans = false; bool stop_other_threads = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); const LazyBool avoid_no_debug = eLazyBoolCalculate; Status new_plan_status; @@ -653,7 +677,7 @@ void SBThread::StepOut(SBError &error) { eVoteNoOpinion, 0, new_plan_status, avoid_no_debug)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -668,8 +692,12 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame) { void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { LLDB_INSTRUMENT_VA(this, sb_frame, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } if (!sb_frame.IsValid()) { error = Status::FromErrorString("passed invalid SBFrame object"); @@ -678,14 +706,14 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { StackFrameSP frame_sp(sb_frame.GetFrameSP()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } bool abort_other_plans = false; bool stop_other_threads = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); if (sb_frame.GetThread().GetThreadID() != thread->GetID()) { error = Status::FromErrorString("passed a frame from another thread"); return; @@ -697,7 +725,7 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -712,21 +740,25 @@ void SBThread::StepInstruction(bool step_over) { void SBThread::StepInstruction(bool step_over, SBError &error) { LLDB_INSTRUMENT_VA(this, step_over, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction( step_over, false, true, new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -741,10 +773,14 @@ void SBThread::RunToAddress(lldb::addr_t addr) { void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) { LLDB_INSTRUMENT_VA(this, addr, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } @@ -754,14 +790,14 @@ void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) { Address target_addr(addr); - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress( abort_other_plans, target_addr, stop_other_threads, new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -773,14 +809,16 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, SBError sb_error; char path[PATH_MAX]; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); StackFrameSP frame_sp(sb_frame.GetFrameSP()); - if (exe_ctx.HasThreadScope()) { - Target *target = exe_ctx.GetTargetPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Target *target = exe_ctx->GetTargetPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); if (line == 0) { sb_error = Status::FromErrorString("invalid line argument"); @@ -875,7 +913,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, frame_sp->GetFrameIndex(), new_plan_status)); if (new_plan_status.Success()) - sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + sb_error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else sb_error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -907,15 +945,17 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, SBError error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return error; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP(); @@ -931,7 +971,7 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, return error; if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); @@ -943,15 +983,17 @@ SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { sb_error = Status::FromErrorString("this SBThread object is invalid"); return sb_error; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status err = thread->JumpToLine(file_spec.ref(), line, true); sb_error.SetError(std::move(err)); @@ -963,11 +1005,13 @@ SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); sb_error.SetError( thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP())); } @@ -980,11 +1024,13 @@ SBError SBThread::UnwindInnermostExpression() { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); sb_error.SetError(thread->UnwindInnermostExpression()); if (sb_error.Success()) thread->SetSelectedFrameByIndex(0, false); @@ -1003,18 +1049,17 @@ bool SBThread::Suspend() { bool SBThread::Suspend(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return false; + } bool result = false; - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended); - result = true; - } else { - error = Status::FromErrorString("process is running"); - } + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->SetResumeState(eStateSuspended); + result = true; } else error = Status::FromErrorString("this SBThread object is invalid"); return result; @@ -1030,19 +1075,19 @@ bool SBThread::Resume() { bool SBThread::Resume(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + error = Status::FromErrorString("process is running"); + return false; + } bool result = false; - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - const bool override_suspend = true; - exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend); - result = true; - } else { - error = Status::FromErrorString("process is running"); - } + if (exe_ctx->HasThreadScope()) { + const bool override_suspend = true; + exe_ctx->GetThreadPtr()->SetResumeState(eStateRunning, override_suspend); + result = true; } else error = Status::FromErrorString("this SBThread object is invalid"); return result; @@ -1051,22 +1096,30 @@ bool SBThread::Resume(SBError &error) { bool SBThread::IsSuspended() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) - return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended; + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetResumeState() == eStateSuspended; return false; } bool SBThread::IsStopped() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) - return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true); + if (exe_ctx->HasThreadScope()) + return StateIsStoppedState(exe_ctx->GetThreadPtr()->GetState(), true); return false; } @@ -1074,13 +1127,17 @@ SBProcess SBThread::GetProcess() { LLDB_INSTRUMENT_VA(this); SBProcess sb_process; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBProcess(); + } - if (exe_ctx.HasThreadScope()) { + if (exe_ctx->HasThreadScope()) { // Have to go up to the target so we can get a shared pointer to our // process... - sb_process.SetSP(exe_ctx.GetProcessSP()); + sb_process.SetSP(exe_ctx->GetProcessSP()); } return sb_process; @@ -1089,34 +1146,33 @@ SBProcess SBThread::GetProcess() { uint32_t SBThread::GetNumFrames() { LLDB_INSTRUMENT_VA(this); - uint32_t num_frames = 0; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } - return num_frames; + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetStackFrameCount(); + + return 0; } SBFrame SBThread::GetFrameAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); SBFrame sb_frame; - StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx); - sb_frame.SetFrameSP(frame_sp); - } + if (exe_ctx->HasThreadScope()) { + StackFrameSP frame_sp = exe_ctx->GetThreadPtr()->GetStackFrameAtIndex(idx); + sb_frame.SetFrameSP(frame_sp); } return sb_frame; @@ -1126,17 +1182,17 @@ lldb::SBFrame SBThread::GetSelectedFrame() { LLDB_INSTRUMENT_VA(this); SBFrame sb_frame; - StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - frame_sp = - exe_ctx.GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame); - sb_frame.SetFrameSP(frame_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } + + if (exe_ctx->HasThreadScope()) { + StackFrameSP frame_sp = + exe_ctx->GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame); + sb_frame.SetFrameSP(frame_sp); } return sb_frame; @@ -1147,18 +1203,19 @@ lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) { SBFrame sb_frame; StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); - frame_sp = thread->GetStackFrameAtIndex(idx); - if (frame_sp) { - thread->SetSelectedFrame(frame_sp.get()); - sb_frame.SetFrameSP(frame_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } + + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); + frame_sp = thread->GetStackFrameAtIndex(idx); + if (frame_sp) { + thread->SetSelectedFrame(frame_sp.get()); + sb_frame.SetFrameSP(frame_sp); } } @@ -1202,12 +1259,16 @@ bool SBThread::GetStatus(SBStream &status) const { Stream &strm = status.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) { - exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true, - /*show_hidden=*/true); + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->GetStatus(strm, 0, 1, 1, true, + /*show_hidden=*/true); } else strm.PutCString("No status"); @@ -1225,11 +1286,15 @@ bool SBThread::GetDescription(SBStream &description, bool stop_format) const { Stream &strm = description.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) { - exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat( + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->DumpUsingSettingsFormat( strm, LLDB_INVALID_THREAD_ID, stop_format); } else strm.PutCString("No value"); @@ -1247,11 +1312,15 @@ SBError SBThread::GetDescriptionWithFormat(const SBFormat &format, return error; } - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error; + } - if (exe_ctx.HasThreadScope()) { - if (exe_ctx.GetThreadPtr()->DumpUsingFormat( + if (exe_ctx->HasThreadScope()) { + if (exe_ctx->GetThreadPtr()->DumpUsingFormat( strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) { return error; } @@ -1267,17 +1336,15 @@ SBError SBThread::GetDescriptionWithFormat(const SBFormat &format, SBThread SBThread::GetExtendedBacktraceThread(const char *type) { LLDB_INSTRUMENT_VA(this, type); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); SBThread sb_origin_thread; - - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - if (exe_ctx.HasThreadScope()) { - ThreadSP real_thread(exe_ctx.GetThreadSP()); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + ThreadSP real_thread(exe_ctx->GetThreadSP()); if (real_thread) { ConstString type_const(type); - Process *process = exe_ctx.GetProcessPtr(); + Process *process = exe_ctx->GetProcessPtr(); if (process) { SystemRuntime *runtime = process->GetSystemRuntime(); if (runtime) { @@ -1293,6 +1360,8 @@ SBThread SBThread::GetExtendedBacktraceThread(const char *type) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); } return sb_origin_thread; diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp index 3f54ea55c9c81..7dc847e097bf8 100644 --- a/lldb/source/Target/ExecutionContext.cpp +++ b/lldb/source/Target/ExecutionContext.cpp @@ -12,7 +12,9 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" +#include using namespace lldb_private; @@ -125,19 +127,47 @@ ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, } } -ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, - std::unique_lock &lock) - : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { - if (exe_ctx_ref_ptr) { - m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); - if (m_target_sp) { - lock = std::unique_lock(m_target_sp->GetAPIMutex()); +llvm::Expected +lldb_private::GetStoppedExecutionContext( + const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr) { + return GetStoppedExecutionContext(exe_ctx_ref_ptr.get()); +} - m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); - m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); - m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); - } - } +llvm::Expected +lldb_private::GetStoppedExecutionContext( + const ExecutionContextRef *exe_ctx_ref_ptr) { + if (!exe_ctx_ref_ptr) + return llvm::createStringError( + "ExecutionContext created with an empty ExecutionContextRef"); + + lldb::TargetSP target_sp = exe_ctx_ref_ptr->GetTargetSP(); + if (!target_sp) + return llvm::createStringError( + "ExecutionContext created with a null target"); + + auto api_lock = + std::unique_lock(target_sp->GetAPIMutex()); + + auto process_sp = exe_ctx_ref_ptr->GetProcessSP(); + if (!process_sp) + return llvm::createStringError( + "ExecutionContext created with a null process"); + + ProcessRunLock::ProcessRunLocker stop_locker; + if (!stop_locker.TryLock(&process_sp->GetRunLock())) + return llvm::createStringError( + "attempted to create an ExecutionContext with a running process"); + + auto thread_sp = exe_ctx_ref_ptr->GetThreadSP(); + auto frame_sp = exe_ctx_ref_ptr->GetFrameSP(); + return StoppedExecutionContext(target_sp, process_sp, thread_sp, frame_sp, + std::move(api_lock), std::move(stop_locker)); +} + +std::unique_lock StoppedExecutionContext::Destroy() { + Clear(); + m_stop_locker = ProcessRunLock::ProcessRunLocker(); + return std::move(m_api_lock); } ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr) diff --git a/lldb/test/API/python_api/run_locker/TestRunLocker.py b/lldb/test/API/python_api/run_locker/TestRunLocker.py index b7b4941214e86..d525bbf6b406f 100644 --- a/lldb/test/API/python_api/run_locker/TestRunLocker.py +++ b/lldb/test/API/python_api/run_locker/TestRunLocker.py @@ -107,4 +107,6 @@ def runlocker_test(self, stop_at_entry): "script var = lldb.frame.EvaluateExpression('SomethingToCall()'); var.GetError().GetCString()", result, ) - self.assertIn("sbframe object is not valid", result.GetOutput()) + self.assertIn( + "can't evaluate expressions when the process is running", result.GetOutput() + )