// Varobj
HRESULT ListVariables(ICorDebugFrame *pFrame, std::string &output);
HRESULT CreateVar(ICorDebugFrame *pFrame, const std::string &varobjName, const std::string &expression, std::string &output);
-HRESULT ListChildren(const std::string &name, int print_values, ICorDebugFrame *pFrame, std::string &output);
+HRESULT ListChildren(const std::string &name, int print_values, ICorDebugThread *pThread, ICorDebugFrame *pFrame, std::string &output);
HRESULT DeleteVar(const std::string &varobjName);
// TypePrinter
return S_OK;
}
-std::mutex g_currentThreadMutex;
-ICorDebugThread *g_currentThread = nullptr;
+static std::mutex g_lastStoppedThreadIdMutex;
+static int g_lastStoppedThreadId = 0;
+
+void SetLastStoppedThread(ICorDebugThread *pThread)
+{
+ DWORD threadId = 0;
+ pThread->GetID(&threadId);
+
+ std::lock_guard<std::mutex> lock(g_lastStoppedThreadIdMutex);
+ g_lastStoppedThreadId = threadId;
+}
+
+int GetLastStoppedThreadId()
+{
+ std::lock_guard<std::mutex> lock(g_lastStoppedThreadIdMutex);
+ return g_lastStoppedThreadId;
+}
class ManagedCallback : public ICorDebugManagedCallback, ICorDebugManagedCallback2
{
out_printf("*stopped,reason=\"breakpoint-hit\",thread-id=\"%i\",stopped-threads=\"all\",bkptno=\"%u\",%s\n",
(int)threadId, (unsigned int)id, output.c_str());
- {
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
- if (g_currentThread)
- g_currentThread->Release();
- pThread->AddRef();
- g_currentThread = pThread;
- }
+
+ SetLastStoppedThread(pThread);
+
return S_OK;
}
out_printf("*stopped,reason=\"end-stepping-range\",thread-id=\"%i\",stopped-threads=\"all\",%s\n",
(int)threadId, output.c_str());
- {
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
- if (g_currentThread)
- g_currentThread->Release();
- pThread->AddRef();
- g_currentThread = pThread;
- }
+ SetLastStoppedThread(pThread);
return S_OK;
}
DWORD threadId = 0;
pThread->GetID(&threadId);
+ SetLastStoppedThread(pThread);
if (unhandled)
{
out_printf("*stopped,reason=\"exception-received\",exception-stage=\"%s\",thread-id=\"%i\",stopped-threads=\"all\",%s\n",
unhandled ? "unhandled" : "handled", (int)threadId, output.c_str());
-
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
- if (g_currentThread)
- g_currentThread->Release();
- pThread->AddRef();
- g_currentThread = pThread;
} else {
out_printf("=message,text=\"Exception thrown: '%s' in %s\\n\",send-to=\"output-window\",source=\"target-exception\"\n",
"<exceptions.name>", "<short.module.name>");
else if (command == "exec-finish")
stepType = STEP_OUT;
- HRESULT hr;
+ ToRelease<ICorDebugThread> pThread;
+ DWORD threadId = GetLastStoppedThreadId();
+ HRESULT hr = pProcess->GetThread(threadId, &pThread);
+ if (SUCCEEDED(hr))
{
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
- hr = g_currentThread ? RunStep(g_currentThread, stepType) : E_FAIL;
+ hr = RunStep(pThread, stepType);
}
if (FAILED(hr))
{
// TODO: Add parsing frame indeces and --thread
std::string output;
- HRESULT hr;
+ ToRelease<ICorDebugThread> pThread;
+ DWORD threadId = GetLastStoppedThreadId();
+ HRESULT hr = pProcess->GetThread(threadId, &pThread);
+ if (SUCCEEDED(hr))
{
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
- hr = g_currentThread ? PrintFrames(g_currentThread, output) : E_FAIL;
+ hr = PrintFrames(pThread, output);
}
if (SUCCEEDED(hr))
{
{
// TODO: Add parsing arguments --thread, --frame
std::string output;
- HRESULT hr;
+ ToRelease<ICorDebugThread> pThread;
+ DWORD threadId = GetLastStoppedThreadId();
+ HRESULT hr = pProcess->GetThread(threadId, &pThread);
+ if (SUCCEEDED(hr))
{
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
-
ToRelease<ICorDebugFrame> pFrame;
- hr = g_currentThread ? g_currentThread->GetActiveFrame(&pFrame) : E_FAIL;
+ hr = pThread->GetActiveFrame(&pFrame);
if (SUCCEEDED(hr))
hr = ListVariables(pFrame, output);
}
} else {
// TODO: Add parsing arguments --thread, --frame
std::string output;
- HRESULT hr;
+ ToRelease<ICorDebugThread> pThread;
+ DWORD threadId = GetLastStoppedThreadId();
+ HRESULT hr = pProcess->GetThread(threadId, &pThread);
+ if (SUCCEEDED(hr))
{
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
-
ToRelease<ICorDebugFrame> pFrame;
- hr = g_currentThread ? g_currentThread->GetActiveFrame(&pFrame) : E_FAIL;
+ hr = pThread->GetActiveFrame(&pFrame);
if (SUCCEEDED(hr))
hr = CreateVar(pFrame, args.at(0), args.at(1), output);
}
} else {
// TODO: Add parsing arguments --thread, --frame
std::string output;
- HRESULT hr;
+ ToRelease<ICorDebugThread> pThread;
+ DWORD threadId = GetLastStoppedThreadId();
+ HRESULT hr = pProcess->GetThread(threadId, &pThread);
+ if (SUCCEEDED(hr))
{
- std::lock_guard<std::mutex> lock(g_currentThreadMutex);
-
ToRelease<ICorDebugFrame> pFrame;
- hr = g_currentThread ? g_currentThread->GetActiveFrame(&pFrame) : E_FAIL;
+ hr = pThread->GetActiveFrame(&pFrame);
if (SUCCEEDED(hr))
- hr = ListChildren(args.at(var_index), print_values, pFrame, output);
+ hr = ListChildren(args.at(var_index), print_values, pThread, pFrame, output);
}
if (SUCCEEDED(hr))
{
typedef std::function<HRESULT(mdMethodDef,ICorDebugModule*,ICorDebugType*,ICorDebugValue*,bool,const std::string&)> WalkMembersCallback;
typedef std::function<HRESULT(ICorDebugILFrame*,ICorDebugValue*,const std::string&)> WalkStackVarsCallback;
-extern std::mutex g_currentThreadMutex;
-extern ICorDebugThread *g_currentThread;
-
-std::mutex g_evalMutex;
-std::condition_variable g_evalCV;
-bool g_evalComplete = false;
+static std::mutex g_evalMutex;
+static std::condition_variable g_evalCV;
+static bool g_evalComplete = false;
void NotifyEvalComplete()
{
}
HRESULT EvalProperty(
+ ICorDebugThread *pThread,
mdMethodDef methodDef,
ICorDebugModule *pModule,
ICorDebugType *pType,
ToRelease<ICorDebugEval> pEval;
ToRelease<ICorDebugProcess> pProcess;
- {
- // g_currentThreadMutex should be locked by caller function
- //std::lock_guard<std::mutex> lock(g_currentThreadMutex);
-
- IfFailRet(g_currentThread->GetProcess(&pProcess));
- IfFailRet(g_currentThread->CreateEval(&pEval));
- }
+ IfFailRet(pThread->GetProcess(&pProcess));
+ IfFailRet(pThread->CreateEval(&pEval));
ToRelease<ICorDebugFunction> pFunc;
IfFailRet(pModule->GetFunctionFromToken(methodDef, &pFunc));
HRESULT WalkMembers(ICorDebugValue *pValue, ICorDebugILFrame *pILFrame, WalkMembersCallback cb);
HRESULT WalkStackVars(ICorDebugFrame *pFrame, WalkStackVarsCallback cb);
HRESULT EvalProperty(
+ ICorDebugThread *pThread,
mdMethodDef methodDef,
ICorDebugModule *pModule,
ICorDebugType *pType,
static HRESULT FetchFieldsAndProperties(ICorDebugValue *pInputValue,
ICorDebugType *pTypeCast,
+ ICorDebugThread *pThread,
ICorDebugILFrame *pILFrame,
std::vector<VarObjValue> &members,
bool static_members,
if (mdGetter != mdMethodDefNil)
{
- EvalProperty(mdGetter, pModule, pType, pInputValue, is_static, &pResultValue);
+ EvalProperty(pThread, mdGetter, pModule, pType, pInputValue, is_static, &pResultValue);
}
else
{
output = ss.str();
}
-HRESULT ListChildren(VarObjValue &objValue, int print_values, ICorDebugFrame *pFrame, std::string &output)
+HRESULT ListChildren(VarObjValue &objValue, int print_values, ICorDebugThread *pThread, ICorDebugFrame *pFrame, std::string &output)
{
HRESULT Status;
IfFailRet(FetchFieldsAndProperties(objValue.value,
NULL,
+ pThread,
pILFrame,
members,
objValue.statics_only,
return S_OK;
}
-HRESULT ListChildren(const std::string &name, int print_values, ICorDebugFrame *pFrame, std::string &output)
+HRESULT ListChildren(const std::string &name, int print_values, ICorDebugThread *pThread, ICorDebugFrame *pFrame, std::string &output)
{
auto it = g_vars.find(name);
if (it == g_vars.end())
return E_FAIL;
- return ListChildren(it->second, print_values, pFrame, output);
+ return ListChildren(it->second, print_values, pThread, pFrame, output);
}
HRESULT ListVariables(ICorDebugFrame *pFrame, std::string &output)