@@ -66,61 +66,65 @@ class CommandObjectIterateOverThreads : public CommandObjectParsed
66
66
if (command.GetArgumentCount () == 0 )
67
67
{
68
68
Thread *thread = m_exe_ctx.GetThreadPtr ();
69
- if (!HandleOneThread (* thread, result))
69
+ if (!HandleOneThread (thread-> GetID () , result))
70
70
return false ;
71
+ return result.Succeeded ();
71
72
}
72
- else if (command.GetArgumentCount () == 1 && ::strcmp (command.GetArgumentAtIndex (0 ), " all" ) == 0 )
73
+
74
+ // Use tids instead of ThreadSPs to prevent deadlocking problems which result from JIT-ing
75
+ // code while iterating over the (locked) ThreadSP list.
76
+ std::vector<lldb::tid_t > tids;
77
+
78
+ if (command.GetArgumentCount () == 1 && ::strcmp (command.GetArgumentAtIndex (0 ), " all" ) == 0 )
73
79
{
74
80
Process *process = m_exe_ctx.GetProcessPtr ();
75
- uint32_t idx = 0 ;
76
- for (ThreadSP thread_sp : process->Threads ())
77
- {
78
- if (idx != 0 && m_add_return)
79
- result.AppendMessage (" " );
80
81
81
- if (!HandleOneThread (*(thread_sp.get ()), result))
82
- return false ;
83
- ++idx;
84
- }
82
+ for (ThreadSP thread_sp : process->Threads ())
83
+ tids.push_back (thread_sp->GetID ());
85
84
}
86
85
else
87
86
{
88
87
const size_t num_args = command.GetArgumentCount ();
89
88
Process *process = m_exe_ctx.GetProcessPtr ();
89
+
90
90
Mutex::Locker locker (process->GetThreadList ().GetMutex ());
91
- std::vector<ThreadSP> thread_sps;
92
91
93
92
for (size_t i = 0 ; i < num_args; i++)
94
93
{
95
94
bool success;
96
-
95
+
97
96
uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex (i), 0 , 0 , &success);
98
97
if (!success)
99
98
{
100
99
result.AppendErrorWithFormat (" invalid thread specification: \" %s\"\n " , command.GetArgumentAtIndex (i));
101
100
result.SetStatus (eReturnStatusFailed);
102
101
return false ;
103
102
}
104
-
105
- thread_sps. push_back ( process->GetThreadList ().FindThreadByIndexID (thread_idx) );
106
-
107
- if (!thread_sps[i] )
103
+
104
+ ThreadSP thread = process->GetThreadList ().FindThreadByIndexID (thread_idx);
105
+
106
+ if (!thread )
108
107
{
109
108
result.AppendErrorWithFormat (" no thread with index: \" %s\"\n " , command.GetArgumentAtIndex (i));
110
109
result.SetStatus (eReturnStatusFailed);
111
110
return false ;
112
111
}
113
- }
114
-
115
- for (uint32_t i = 0 ; i < num_args; i++)
116
- {
117
- if (!HandleOneThread (*(thread_sps[i].get ()), result))
118
- return false ;
119
112
120
- if (i < num_args - 1 && m_add_return)
121
- result.AppendMessage (" " );
113
+ tids.push_back (thread->GetID ());
122
114
}
123
115
}
116
+
117
+ uint32_t idx = 0 ;
118
+ for (const lldb::tid_t &tid : tids)
119
+ {
120
+ if (idx != 0 && m_add_return)
121
+ result.AppendMessage (" " );
122
+
123
+ if (!HandleOneThread (tid, result))
124
+ return false ;
125
+
126
+ ++idx;
127
+ }
124
128
return result.Succeeded ();
125
129
}
126
130
@@ -133,7 +137,7 @@ class CommandObjectIterateOverThreads : public CommandObjectParsed
133
137
// If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
134
138
135
139
virtual bool
136
- HandleOneThread (Thread &thread , CommandReturnObject &result) = 0 ;
140
+ HandleOneThread (lldb:: tid_t , CommandReturnObject &result) = 0 ;
137
141
138
142
ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
139
143
bool m_add_return = true ;
@@ -275,25 +279,35 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
275
279
}
276
280
277
281
bool
278
- HandleOneThread (Thread &thread , CommandReturnObject &result) override
282
+ HandleOneThread (lldb:: tid_t tid , CommandReturnObject &result) override
279
283
{
284
+ ThreadSP thread_sp = m_exe_ctx.GetProcessPtr ()->GetThreadList ().FindThreadByID (tid);
285
+ if (!thread_sp)
286
+ {
287
+ result.AppendErrorWithFormat (" thread disappeared while computing backtraces: 0x%" PRIx64 " \n " , tid);
288
+ result.SetStatus (eReturnStatusFailed);
289
+ return false ;
290
+ }
291
+
292
+ Thread *thread = thread_sp.get ();
293
+
280
294
Stream &strm = result.GetOutputStream ();
281
295
282
296
// Don't show source context when doing backtraces.
283
297
const uint32_t num_frames_with_source = 0 ;
284
298
285
- if (!thread. GetStatus (strm,
286
- m_options.m_start ,
287
- m_options.m_count ,
288
- num_frames_with_source))
299
+ if (!thread-> GetStatus (strm,
300
+ m_options.m_start ,
301
+ m_options.m_count ,
302
+ num_frames_with_source))
289
303
{
290
- result.AppendErrorWithFormat (" error displaying backtrace for thread: \" 0x%4.4x\"\n " , thread. GetIndexID ());
304
+ result.AppendErrorWithFormat (" error displaying backtrace for thread: \" 0x%4.4x\"\n " , thread-> GetIndexID ());
291
305
result.SetStatus (eReturnStatusFailed);
292
306
return false ;
293
307
}
294
308
if (m_options.m_extended_backtrace )
295
309
{
296
- DoExtendedBacktrace (& thread, result);
310
+ DoExtendedBacktrace (thread, result);
297
311
}
298
312
299
313
return true ;
@@ -1537,12 +1551,22 @@ class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
1537
1551
}
1538
1552
1539
1553
bool
1540
- HandleOneThread (Thread &thread , CommandReturnObject &result) override
1554
+ HandleOneThread (lldb:: tid_t tid , CommandReturnObject &result) override
1541
1555
{
1556
+ ThreadSP thread_sp = m_exe_ctx.GetProcessPtr ()->GetThreadList ().FindThreadByID (tid);
1557
+ if (!thread_sp)
1558
+ {
1559
+ result.AppendErrorWithFormat (" thread no longer exists: 0x%" PRIx64 " \n " , tid);
1560
+ result.SetStatus (eReturnStatusFailed);
1561
+ return false ;
1562
+ }
1563
+
1564
+ Thread *thread = thread_sp.get ();
1565
+
1542
1566
Stream &strm = result.GetOutputStream ();
1543
- if (!thread. GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread , m_options.m_json_stopinfo ))
1567
+ if (!thread-> GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread , m_options.m_json_stopinfo ))
1544
1568
{
1545
- result.AppendErrorWithFormat (" error displaying info for thread: \" %d\"\n " , thread. GetIndexID ());
1569
+ result.AppendErrorWithFormat (" error displaying info for thread: \" %d\"\n " , thread-> GetIndexID ());
1546
1570
result.SetStatus (eReturnStatusFailed);
1547
1571
return false ;
1548
1572
}
@@ -2044,14 +2068,24 @@ class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
2044
2068
2045
2069
protected:
2046
2070
bool
2047
- HandleOneThread (Thread &thread , CommandReturnObject &result) override
2071
+ HandleOneThread (lldb:: tid_t tid , CommandReturnObject &result) override
2048
2072
{
2073
+ ThreadSP thread_sp = m_exe_ctx.GetProcessPtr ()->GetThreadList ().FindThreadByID (tid);
2074
+ if (!thread_sp)
2075
+ {
2076
+ result.AppendErrorWithFormat (" thread no longer exists: 0x%" PRIx64 " \n " , tid);
2077
+ result.SetStatus (eReturnStatusFailed);
2078
+ return false ;
2079
+ }
2080
+
2081
+ Thread *thread = thread_sp.get ();
2082
+
2049
2083
Stream &strm = result.GetOutputStream ();
2050
2084
DescriptionLevel desc_level = eDescriptionLevelFull;
2051
2085
if (m_options.m_verbose )
2052
2086
desc_level = eDescriptionLevelVerbose;
2053
2087
2054
- thread. DumpThreadPlans (&strm, desc_level, m_options.m_internal , true );
2088
+ thread-> DumpThreadPlans (&strm, desc_level, m_options.m_internal , true );
2055
2089
return true ;
2056
2090
}
2057
2091
0 commit comments