Index: packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile +++ packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +LDFLAGS=-pthread + +CXX_SOURCES := test_threadinfo.cpp + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py +++ packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py @@ -0,0 +1,39 @@ +""" +Test lldb-mi -thread-info command. +""" + +from __future__ import print_function + +import lldbmi_testcase +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class MiThreadInfoTestCase(lldbmi_testcase.MiTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # pthreads not supported on Windows + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + def test_lldbmi_thread_info(self): + """Test that -thread-info prints thread info and the current-thread-id""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + self.runCmd("-break-insert ThreadProc") + self.expect("\^done") + + # Run to the breakpoint + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + self.runCmd("-thread-info") + self.expect("\^done,threads=\[\{id=\"1\",(.*)\},\{id=\"2\",(.*)\],current-thread-id=\"2\"") + + self.runCmd("-gdb-quit") + Index: packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp +++ packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + + +void* ThreadProc(void* arg) +{ + int i = 0; + i++; + return NULL; +} + +int main() +{ + pthread_t thread; + pthread_create(&thread, NULL, ThreadProc, NULL); + pthread_join(thread, NULL); + return 0; +} Index: tools/lldb-mi/MICmdCmdThread.h =================================================================== --- tools/lldb-mi/MICmdCmdThread.h +++ tools/lldb-mi/MICmdCmdThread.h @@ -60,4 +60,8 @@ bool m_bThreadInvalid; // True = invalid, false = ok VecMIValueTuple_t m_vecMIValueTuple; const CMIUtilString m_constStrArgNamedThreadId; + + // mi value of current-thread-id if multiple threads are requested + bool m_bHasCurrentThread; + CMICmnMIValue m_miValueCurrThreadId; }; Index: tools/lldb-mi/MICmdCmdThread.cpp =================================================================== --- tools/lldb-mi/MICmdCmdThread.cpp +++ tools/lldb-mi/MICmdCmdThread.cpp @@ -32,6 +32,7 @@ : m_bSingleThread(false) , m_bThreadInvalid(true) , m_constStrArgNamedThreadId("thread-id") + , m_bHasCurrentThread(false) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "thread-info"; @@ -123,6 +124,15 @@ m_vecMIValueTuple.push_back(miTuple); } } + + // -thread-info with multiple threads ends with the current thread id if any + if (thread.IsValid()) + { + const CMIUtilString strId(CMIUtilString::Format("%d", thread.GetIndexID())); + CMICmnMIValueConst miValueCurrThreadId(strId); + m_miValueCurrThreadId = miValueCurrThreadId; + m_bHasCurrentThread = true; + } return MIstatus::success; } @@ -179,7 +189,12 @@ ++it; } - const CMICmnMIValueResult miValueResult("threads", miValueList); + CMICmnMIValueResult miValueResult("threads", miValueList); + if (m_bHasCurrentThread) + { + CMIUtilString strCurrThreadId = "current-thread-id"; + miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId); + } const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); m_miResultRecord = miRecordResult;