The dynamics of this bug is like this:
- Thread A calls
BinaryNinjaDebugger::DbgEngAdapter::Wait(duration<…>) dbgengadapter.cpp:979, which obtains an internal lock of DbgEng (invisible to us)
- Main thread calls
BinaryNinjaDebugger::DbgEngAdapter::GetInstructionOffset() which also requires the internal lock, and then blocks
- Thread A gets an output message from the dbgeng, and then calls
PostDebuggerEvent, which needs to run on the main thread.
- The main thread is still blocking so the BN hangs
The stacktrafce of the main thread:
0x00007ffd1ac529f4
0x00007ffd1abe42d3
0x00007ffd1abd1f64
0x00007ffd1abd1d52
0x00007ffcae1e7eb5
BinaryNinjaDebugger::DbgEngAdapter::GetInstructionOffset() dbgengadapter.cpp:1089
BinaryNinjaDebugger::DbgEngAdapter::GetActiveThread() dbgengadapter.cpp:611
BinaryNinjaDebugger::DebuggerThreads::GetActiveThread() debuggerstate.cpp:218
BinaryNinjaDebugger::DebuggerController::GetActiveThread() debuggercontroller.cpp:659
BNDebuggerGetActiveThread(BNDebuggerController *) ffi.cpp:227
BinaryNinjaDebuggerAPI::DebuggerController::GetActiveThread() debuggercontroller.cpp:136
ThreadFramesWidget::updateContent() threadframes.cpp:366
ThreadFramesWidget::ThreadFramesWidget(QWidget *, ViewFrame *, Ref<…>) threadframes.cpp:344
GlobalThreadFramesContainer::notifyViewChanged(ViewFrame *) threadframes.cpp:492
0x00007ffca53c4ece
0x00007ffca5219352
0x00007ff6a38857b8
0x00007ffca51f2ebf
0x00007ffca4bb2957
0x00007ffca639d696
0x00007ffca6426423
0x00007ffca64223a7
0x00007ffca6360fae
0x00007ffca63601ca
0x00007ffca4b70d05
0x00007ffca4b7311f
0x00007ffca419cd9f
0x00007ffca4cc7655
0x00007ffca419cd79
0x00007ffca5309d1b
DebugControlsWidget::performLaunch() controlswidget.cpp:116
0x00007ffca4baa581
0x00007ffca4bac8a4
0x00007ffca41d00f1
0x00007ffca644e377
0x00007ffca644f7e0
0x00007ffca65380cf
0x00007ffca639c990
0x00007ffca6360fae
0x00007ffca635f17e
0x00007ffca4b70d05
0x00007ffca63649c2
0x00007ffca63ba669
0x00007ffca63b7eab
0x00007ffca6360fae
0x00007ffca63601ca
0x00007ffca4b70d05
0x00007ffca3f15406
0x00007ffca3f60848
0x00007ffca4cc7655
0x00007ffca419cd79
0x00007ffca4b763e4
0x00007ffca4b6f00d
0x00007ff6a3818845
0x00007ff6a3a3c100
0x00007ffd19c5244d
0x00007ffd1ac0dfb8
The stacktrace of a related thread:
0x00007ffd1ac529f4
0x00007ffd1ac1987b
0x00007ffd181f6979
0x00007ffcc28d2c09
0x00007ffcc28d2e9a
0x00007ffc94308c8c
0x00007ffc9430916b
BinaryNinja::ExecuteOnMainThreadAndWait(const std::function<…> &) mainthread.cpp:109
BinaryNinjaDebugger::DebuggerController::PostDebuggerEvent(const BinaryNinjaDebugger::DebuggerEvent &) debuggercontroller.cpp:1095
BinaryNinjaDebugger::DbgEngOutputCallbacks::Output(unsigned long, const char *) dbgengadapter.cpp:1215
0x00007ffcae19b0a8
0x00007ffcae1a0202
0x00007ffcae1a032a
0x00007ffcae1a1100
0x00007ffcae1a1317
0x00007ffcae1a140c
0x00007ffcae1a14e6
0x00007ffcae19e596
0x00007ffcae19dcc3
0x00007ffcae2615c6
0x00007ffcae261130
0x00007ffcae1d0b15
0x00007ffcae1d1118
BinaryNinjaDebugger::DbgEngAdapter::Wait(duration<…>) dbgengadapter.cpp:979
BinaryNinjaDebugger::DbgEngAdapter::ExecuteWithArgsInternal(const std::string &, const std::string &, const std::string &, const BinaryNinjaDebugger::LaunchConfigurations &) dbgengadapter.cpp:393
[Inlined] BinaryNinjaDebugger::DbgEngAdapter::ExecuteWithArgs::__l2::<lambda_19080241...>::operator()() dbgengadapter.cpp:327
[Inlined] std::invoke(<lambda_19080241...> &&) type_traits:1480
std::thread::_Invoke<…>(void *) thread:55
0x00007ffd188b9363
0x00007ffd19c5244d
0x00007ffd1ac0dfb8
The stacktrace of another related thread:
[Inlined] std::_Atomic_storage::load() atomic:667
[Inlined] std::atomic::operator bool() atomic:2315
BinaryNinjaDebugger::DbgEngAdapter::ExecuteWithArgs(const std::string &, const std::string &, const std::string &, const BinaryNinjaDebugger::LaunchConfigurations &) dbgengadapter.cpp:333
BinaryNinjaDebugger::DebuggerController::Execute() debuggercontroller.cpp:176
BinaryNinjaDebugger::DebuggerController::Launch() debuggercontroller.cpp:126
[Inlined] DebugControlsWidget::performLaunch::__l2::<lambda_5436fc5fa90232b939d43bfc2aa356dd>::operator()(function<bool __cdecl(unsigned __int64,unsigned __int64)>) controlswidget.cpp:109
[Inlined] std::invoke(<lambda_5436fc5fa90232b939d43bfc2aa356dd> &,std::function<bool __cdecl(unsigned __int64,unsigned __int64)> &&) type_traits:1490
[Inlined] std::_Invoker_ret<void,1>::_Call(<lambda_5436fc5fa90232b939d43bfc2aa356dd> &,std::function<bool __cdecl(unsigned __int64,unsigned __int64)> &&) functional:664
std::_Func_impl_no_alloc<<lambda_5436fc5fa90232b939d43bfc2aa356dd>,void,std::function<bool __cdecl(unsigned __int64,unsigned __int64)> >::_Do_call(std::function<bool __cdecl(unsigned __int64,unsigned __int64)> &&) functional:833
0x00007ffca5309936
0x00007ffca53079b1
0x00007ffd188b9363
0x00007ffd19c5244d
0x00007ffd1ac0dfb8