TestConcurrentEvents.py revision ff5c6d9c07c02c80b24a59c25d9f5edd518479c4
1""" 2A stress-test of sorts for LLDB's handling of threads in the inferior. 3 4This test sets a breakpoint in the main thread where test parameters (numbers of 5threads) can be adjusted, runs the inferior to that point, and modifies the 6locals that control the event thread counts. This test also sets a breakpoint in 7breakpoint_func (the function executed by each 'breakpoint' thread) and a 8watchpoint on a global modified in watchpoint_func. The inferior is continued 9until exit or a crash takes place, and the number of events seen by LLDB is 10verified to match the expected number of events. 11""" 12 13import os, time 14import unittest2 15import lldb 16from lldbtest import * 17import lldbutil 18 19class ConcurrentEventsTestCase(TestBase): 20 21 mydir = os.path.join("functionalities", "thread", "concurrent_events") 22 23 # 24 ## Tests for multiple threads that generate a single event. 25 # 26 @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") 27 @dwarf_test 28 def test_many_breakpoints_dwarf(self): 29 """Test 100 breakpoints from 100 threads.""" 30 self.buildDwarf(dictionary=self.getBuildFlags()) 31 self.do_thread_actions(num_breakpoint_threads=100) 32 33 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 34 @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") 35 @dwarf_test 36 def test_many_watchpoints_dwarf(self): 37 """Test 100 watchpoints from 100 threads.""" 38 self.buildDwarf(dictionary=self.getBuildFlags()) 39 self.do_thread_actions(num_watchpoint_threads=100) 40 41 @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") 42 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 43 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 44 @dwarf_test 45 def test_many_signals_dwarf(self): 46 """Test 100 signals from 100 threads.""" 47 self.buildDwarf(dictionary=self.getBuildFlags()) 48 self.do_thread_actions(num_signal_threads=100) 49 50 @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") 51 @dwarf_test 52 def test_many_crash_dwarf(self): 53 """Test 100 threads that cause a segfault.""" 54 self.buildDwarf(dictionary=self.getBuildFlags()) 55 self.do_thread_actions(num_crash_threads=100) 56 57 58 # 59 ## Tests for concurrent signal and breakpoint 60 # 61 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 62 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 63 @dwarf_test 64 def test_signal_break_dwarf(self): 65 """Test signal and a breakpoint in multiple threads.""" 66 self.buildDwarf(dictionary=self.getBuildFlags()) 67 self.do_thread_actions(num_breakpoint_threads=1, num_signal_threads=1) 68 69 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 70 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 71 @dwarf_test 72 def test_delay_signal_break_dwarf(self): 73 """Test (1-second delay) signal and a breakpoint in multiple threads.""" 74 self.buildDwarf(dictionary=self.getBuildFlags()) 75 self.do_thread_actions(num_breakpoint_threads=1, num_delay_signal_threads=1) 76 77 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 78 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 79 @dwarf_test 80 def test_signal_delay_break_dwarf(self): 81 """Test signal and a (1 second delay) breakpoint in multiple threads.""" 82 self.buildDwarf(dictionary=self.getBuildFlags()) 83 self.do_thread_actions(num_delay_breakpoint_threads=1, num_signal_threads=1) 84 85 86 # 87 ## Tests for concurrent watchpoint and breakpoint 88 # 89 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 90 @dwarf_test 91 def test_watch_break_dwarf(self): 92 """Test watchpoint and a breakpoint in multiple threads.""" 93 self.buildDwarf(dictionary=self.getBuildFlags()) 94 self.do_thread_actions(num_breakpoint_threads=1, num_watchpoint_threads=1) 95 96 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 97 @dwarf_test 98 def test_delay_watch_break_dwarf(self): 99 """Test (1-second delay) watchpoint and a breakpoint in multiple threads.""" 100 self.buildDwarf(dictionary=self.getBuildFlags()) 101 self.do_thread_actions(num_breakpoint_threads=1, num_delay_watchpoint_threads=1) 102 103 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 104 @dwarf_test 105 def test_watch_break_dwarf(self): 106 """Test watchpoint and a (1 second delay) breakpoint in multiple threads.""" 107 self.buildDwarf(dictionary=self.getBuildFlags()) 108 self.do_thread_actions(num_delay_breakpoint_threads=1, num_watchpoint_threads=1) 109 110 # 111 ## Tests for concurrent signal and watchpoint 112 # 113 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 114 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 115 @dwarf_test 116 def test_signal_watch_dwarf(self): 117 """Test a watchpoint and a signal in multiple threads.""" 118 self.buildDwarf(dictionary=self.getBuildFlags()) 119 self.do_thread_actions(num_signal_threads=1, num_watchpoint_threads=1) 120 121 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 122 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 123 @dwarf_test 124 def test_delay_signal_watch_dwarf(self): 125 """Test a watchpoint and a (1 second delay) signal in multiple threads.""" 126 self.buildDwarf(dictionary=self.getBuildFlags()) 127 self.do_thread_actions(num_delay_signal_threads=1, num_watchpoint_threads=1) 128 129 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 130 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 131 @dwarf_test 132 def test_signal_delay_watch_dwarf(self): 133 """Test a (1 second delay) watchpoint and a signal in multiple threads.""" 134 self.buildDwarf(dictionary=self.getBuildFlags()) 135 self.do_thread_actions(num_signal_threads=1, num_delay_watchpoint_threads=1) 136 137 138 # 139 ## Tests for multiple breakpoint threads 140 # 141 @dwarf_test 142 def test_two_breakpoint_threads_dwarf(self): 143 """Test two threads that trigger a breakpoint. """ 144 self.buildDwarf(dictionary=self.getBuildFlags()) 145 self.do_thread_actions(num_breakpoint_threads=2) 146 147 @dwarf_test 148 def test_breakpoint_one_delay_breakpoint_threads_dwarf(self): 149 """Test threads that trigger a breakpoint where one thread has a 1 second delay. """ 150 self.buildDwarf(dictionary=self.getBuildFlags()) 151 self.do_thread_actions(num_breakpoint_threads=1, 152 num_delay_breakpoint_threads=1) 153 154 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 155 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 156 @dwarf_test 157 def test_two_breakpoints_one_signal_dwarf(self): 158 """Test two threads that trigger a breakpoint and one signal thread. """ 159 self.buildDwarf(dictionary=self.getBuildFlags()) 160 self.do_thread_actions(num_breakpoint_threads=2, num_signal_threads=1) 161 162 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 163 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 164 @dwarf_test 165 def test_breakpoint_delay_breakpoint_one_signal_dwarf(self): 166 """Test two threads that trigger a breakpoint (one with a 1 second delay) and one signal thread. """ 167 self.buildDwarf(dictionary=self.getBuildFlags()) 168 self.do_thread_actions(num_breakpoint_threads=1, 169 num_delay_breakpoint_threads=1, 170 num_signal_threads=1) 171 172 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 173 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 174 @dwarf_test 175 def test_two_breakpoints_one_delay_signal_dwarf(self): 176 """Test two threads that trigger a breakpoint and one (1 second delay) signal thread. """ 177 self.buildDwarf(dictionary=self.getBuildFlags()) 178 self.do_thread_actions(num_breakpoint_threads=2, num_delay_signal_threads=1) 179 180 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 181 @dwarf_test 182 def test_two_breakpoints_one_watchpoint_dwarf(self): 183 """Test two threads that trigger a breakpoint and one watchpoint thread. """ 184 self.buildDwarf(dictionary=self.getBuildFlags()) 185 self.do_thread_actions(num_breakpoint_threads=2, num_watchpoint_threads=1) 186 187 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 188 @dwarf_test 189 def test_breakpoints_delayed_breakpoint_one_watchpoint_dwarf(self): 190 """Test a breakpoint, a delayed breakpoint, and one watchpoint thread. """ 191 self.buildDwarf(dictionary=self.getBuildFlags()) 192 self.do_thread_actions(num_breakpoint_threads=1, 193 num_delay_breakpoint_threads=1, 194 num_watchpoint_threads=1) 195 196 # 197 ## Tests for multiple watchpoint threads 198 # 199 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 200 @dwarf_test 201 def test_two_watchpoint_threads_dwarf(self): 202 """Test two threads that trigger a watchpoint. """ 203 self.buildDwarf(dictionary=self.getBuildFlags()) 204 self.do_thread_actions(num_watchpoint_threads=2) 205 206 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 207 @dwarf_test 208 def test_watchpoint_with_delay_waychpoint_threads_dwarf(self): 209 """Test two threads that trigger a watchpoint where one thread has a 1 second delay. """ 210 self.buildDwarf(dictionary=self.getBuildFlags()) 211 self.do_thread_actions(num_watchpoint_threads=1, 212 num_delay_watchpoint_threads=1) 213 214 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 215 @dwarf_test 216 def test_two_watchpoints_one_breakpoint_dwarf(self): 217 """Test two threads that trigger a watchpoint and one breakpoint thread. """ 218 self.buildDwarf(dictionary=self.getBuildFlags()) 219 self.do_thread_actions(num_watchpoint_threads=2, num_breakpoint_threads=1) 220 221 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 222 @dwarf_test 223 def test_two_watchpoints_one_delay_breakpoint_dwarf(self): 224 """Test two threads that trigger a watchpoint and one (1 second delay) breakpoint thread. """ 225 self.buildDwarf(dictionary=self.getBuildFlags()) 226 self.do_thread_actions(num_watchpoint_threads=2, num_delay_breakpoint_threads=1) 227 228 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 229 @dwarf_test 230 def test_watchpoint_delay_watchpoint_one_breakpoint_dwarf(self): 231 """Test two threads that trigger a watchpoint (one with a 1 second delay) and one breakpoint thread. """ 232 self.buildDwarf(dictionary=self.getBuildFlags()) 233 self.do_thread_actions(num_watchpoint_threads=1, 234 num_delay_watchpoint_threads=1, 235 num_breakpoint_threads=1) 236 237 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 238 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 239 @dwarf_test 240 def test_two_watchpoints_one_signal_dwarf(self): 241 """Test two threads that trigger a watchpoint and one signal thread. """ 242 self.buildDwarf(dictionary=self.getBuildFlags()) 243 self.do_thread_actions(num_watchpoint_threads=2, num_signal_threads=1) 244 245 # 246 ## Test for watchpoint, signal and breakpoint happening concurrently 247 # 248 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 249 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 250 @dwarf_test 251 def test_signal_watch_break_dwarf(self): 252 """Test a signal/watchpoint/breakpoint in multiple threads.""" 253 self.buildDwarf(dictionary=self.getBuildFlags()) 254 self.do_thread_actions(num_signal_threads=1, 255 num_watchpoint_threads=1, 256 num_breakpoint_threads=1) 257 258 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 259 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 260 @dwarf_test 261 def test_signal_watch_break_dwarf(self): 262 """Test one signal thread with 5 watchpoint and breakpoint threads.""" 263 self.buildDwarf(dictionary=self.getBuildFlags()) 264 self.do_thread_actions(num_signal_threads=1, 265 num_watchpoint_threads=5, 266 num_breakpoint_threads=5) 267 268 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 269 @dwarf_test 270 def test_signal_watch_break_dwarf(self): 271 """Test with 5 watchpoint and breakpoint threads.""" 272 self.buildDwarf(dictionary=self.getBuildFlags()) 273 self.do_thread_actions(num_watchpoint_threads=5, 274 num_breakpoint_threads=5) 275 276 277 # 278 ## Test for crashing threads happening concurrently with other events 279 # 280 @dwarf_test 281 def test_crash_with_break_dwarf(self): 282 """ Test a thread that crashes while another thread hits a breakpoint.""" 283 self.buildDwarf(dictionary=self.getBuildFlags()) 284 self.do_thread_actions(num_crash_threads=1, num_breakpoint_threads=1) 285 286 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 287 @dwarf_test 288 def test_crash_with_watchpoint_dwarf(self): 289 """ Test a thread that crashes while another thread hits a watchpoint.""" 290 self.buildDwarf(dictionary=self.getBuildFlags()) 291 self.do_thread_actions(num_crash_threads=1, num_watchpoint_threads=1) 292 293 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 294 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 295 @dwarf_test 296 def test_crash_with_signal_dwarf(self): 297 """ Test a thread that crashes while another thread generates a signal.""" 298 self.buildDwarf(dictionary=self.getBuildFlags()) 299 self.do_thread_actions(num_crash_threads=1, num_signal_threads=1) 300 301 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 302 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 303 @dwarf_test 304 def test_crash_with_watchpoint_breakpoint_signal_dwarf(self): 305 """ Test a thread that crashes while other threads generate a signal and hit a watchpoint and breakpoint. """ 306 self.buildDwarf(dictionary=self.getBuildFlags()) 307 self.do_thread_actions(num_crash_threads=1, 308 num_breakpoint_threads=1, 309 num_signal_threads=1, 310 num_watchpoint_threads=1) 311 312 @skipIfDarwin # llvm.org/pr16566 -- new threads do not respect watchpoints 313 @skipIfLinux # inferior thread enters state D (disk sleep) which causes hang in lldb 314 @dwarf_test 315 def test_delayed_crash_with_breakpoint_watchpoint_dwarf(self): 316 """ Test a thread with a delayed crash while other threads hit a watchpoint and a breakpoint. """ 317 self.buildDwarf(dictionary=self.getBuildFlags()) 318 self.do_thread_actions(num_delay_crash_threads=1, 319 num_breakpoint_threads=1, 320 num_watchpoint_threads=1) 321 322 @skipIfDarwin # llvm.org/pr16567 -- thread count is incorrect during signal delivery 323 @skipIfLinux # llvm.org/pr16567 -- explicit signals cause hangs on Linux 324 @dwarf_test 325 def test_delayed_crash_with_breakpoint_signal_dwarf(self): 326 """ Test a thread with a delayed crash while other threads generate a signal and hit a breakpoint. """ 327 self.buildDwarf(dictionary=self.getBuildFlags()) 328 self.do_thread_actions(num_delay_crash_threads=1, 329 num_breakpoint_threads=1, 330 num_signal_threads=1) 331 332 333 def setUp(self): 334 # Call super's setUp(). 335 TestBase.setUp(self) 336 # Find the line number for our breakpoint. 337 self.thread_breakpoint = line_number('main.cpp', '// Set breakpoint here') 338 self.setup_breakpoint = line_number('main.cpp', '// Break here and adjust num') 339 340 def print_threads(self, threads): 341 ret = "" 342 for x in threads: 343 ret += "\t thread %d stopped due to reason %s" % (x.GetIndexID(), lldbutil.stop_reason_to_str(x.GetStopReason())) 344 return ret 345 346 def debug_threads(self, bps, crashed, exiting, wps, signals, others): 347 print "%d threads stopped at bp:\n%s" % (len(bps), self.print_threads(bps)) 348 print "%d threads crashed:\n%s" % (len(crashed), self.print_threads(crashed)) 349 print "%d threads stopped due to watchpoint:\n%s" % (len(wps), self.print_threads(wps)) 350 print "%d threads stopped at signal:\n%s" % (len(signals), self.print_threads(signals)) 351 print "%d threads exiting:\n%s" % (len(exiting), self.print_threads(exiting)) 352 print "%d threads stopped due to other/unknown reason:\n%s" % (len(others), self.print_threads(others)) 353 354 def do_thread_actions(self, 355 num_breakpoint_threads = 0, 356 num_signal_threads = 0, 357 num_watchpoint_threads = 0, 358 num_crash_threads = 0, 359 num_delay_breakpoint_threads = 0, 360 num_delay_signal_threads = 0, 361 num_delay_watchpoint_threads = 0, 362 num_delay_crash_threads = 0): 363 """ Sets a breakpoint in the main thread where test parameters (numbers of threads) can be adjusted, runs the inferior 364 to that point, and modifies the locals that control the event thread counts. Also sets a breakpoint in 365 breakpoint_func (the function executed by each 'breakpoint' thread) and a watchpoint on a global modified in 366 watchpoint_func. The inferior is continued until exit or a crash takes place, and the number of events seen by LLDB 367 is verified to match the expected number of events. 368 """ 369 exe = os.path.join(os.getcwd(), "a.out") 370 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 371 372 # Initialize all the breakpoints (main thread/aux thread) 373 lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.setup_breakpoint, 374 num_expected_locations=1) 375 lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.thread_breakpoint, 376 num_expected_locations=1) 377 378 # The breakpoint list should show 2 breakpoints with 1 location. 379 self.expect("breakpoint list -f", "Breakpoint location shown correctly", 380 substrs = ["1: file = 'main.cpp', line = %d, locations = 1" % self.setup_breakpoint, 381 "2: file = 'main.cpp', line = %d, locations = 1" % self.thread_breakpoint]) 382 383 # Run the program. 384 self.runCmd("run", RUN_SUCCEEDED) 385 386 # Check we are at line self.setup_breakpoint 387 self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, 388 substrs = ["stop reason = breakpoint 1."]) 389 390 # Initialize the watchpoint on the global variable (g_watchme) 391 if num_watchpoint_threads + num_delay_watchpoint_threads > 0: 392 self.runCmd("watchpoint set variable g_watchme") 393 394 # Get the target process 395 target = self.dbg.GetSelectedTarget() 396 process = target.GetProcess() 397 398 # We should be stopped at the setup site where we can set the number of 399 # threads doing each action (break/crash/signal/watch) 400 self.assertEqual(process.GetNumThreads(), 1, 'Expected to stop before any additional threads are spawned.') 401 402 self.runCmd("expr num_breakpoint_threads=%d" % num_breakpoint_threads) 403 self.runCmd("expr num_crash_threads=%d" % num_crash_threads) 404 self.runCmd("expr num_signal_threads=%d" % num_signal_threads) 405 self.runCmd("expr num_watchpoint_threads=%d" % num_watchpoint_threads) 406 407 self.runCmd("expr num_delay_breakpoint_threads=%d" % num_delay_breakpoint_threads) 408 self.runCmd("expr num_delay_crash_threads=%d" % num_delay_crash_threads) 409 self.runCmd("expr num_delay_signal_threads=%d" % num_delay_signal_threads) 410 self.runCmd("expr num_delay_watchpoint_threads=%d" % num_delay_watchpoint_threads) 411 412 self.runCmd("continue") 413 414 # Make sure we see all the threads. The inferior program's threads all synchronize with a pseudo-barrier; that is, 415 # the inferior program ensures all threads are started and running before any thread triggers its 'event'. 416 num_threads = process.GetNumThreads() 417 expected_num_threads = num_breakpoint_threads + num_delay_breakpoint_threads \ 418 + num_signal_threads + num_delay_signal_threads \ 419 + num_watchpoint_threads + num_delay_watchpoint_threads \ 420 + num_crash_threads + num_delay_crash_threads + 1 421 self.assertEqual(num_threads, expected_num_threads, 422 'Number of expected threads and actual threads do not match.') 423 424 # Get the thread objects 425 (breakpoint_threads, crashed_threads, exiting_threads, other_threads, signal_threads, watchpoint_threads) = ([], [], [], [], [], []) 426 lldbutil.sort_stopped_threads(process, 427 breakpoint_threads=breakpoint_threads, 428 crashed_threads=crashed_threads, 429 exiting_threads=exiting_threads, 430 signal_threads=signal_threads, 431 watchpoint_threads=watchpoint_threads, 432 other_threads=other_threads) 433 434 if self.TraceOn(): 435 self.debug_threads(breakpoint_threads, crashed_threads, exiting_threads, watchpoint_threads, signal_threads, other_threads) 436 437 # The threads that are doing signal handling must be unblocked or the inferior will hang. We keep 438 # a counter of threads that stop due to a signal so we have something to verify later on. 439 seen_signal_threads = len(signal_threads) 440 seen_breakpoint_threads = len(breakpoint_threads) 441 seen_watchpoint_threads = len(watchpoint_threads) 442 seen_crashed_threads = len(crashed_threads) 443 444 # Run to completion 445 while len(crashed_threads) == 0 and process.GetState() != lldb.eStateExited: 446 if self.TraceOn(): 447 self.runCmd("thread backtrace all") 448 self.debug_threads(breakpoint_threads, crashed_threads, exiting_threads, watchpoint_threads, signal_threads, other_threads) 449 450 self.runCmd("continue") 451 lldbutil.sort_stopped_threads(process, 452 breakpoint_threads=breakpoint_threads, 453 crashed_threads=crashed_threads, 454 exiting_threads=exiting_threads, 455 signal_threads=signal_threads, 456 watchpoint_threads=watchpoint_threads, 457 other_threads=other_threads) 458 seen_signal_threads += len(signal_threads) 459 seen_breakpoint_threads += len(breakpoint_threads) 460 seen_watchpoint_threads += len(watchpoint_threads) 461 seen_crashed_threads += len(crashed_threads) 462 463 if num_crash_threads > 0 or num_delay_crash_threads > 0: 464 # Expecting a crash 465 self.assertTrue(seen_crashed_threads > 0, "Expecting at least one thread to crash") 466 467 # Ensure the zombie process is reaped 468 self.runCmd("process kill") 469 470 elif num_crash_threads == 0 and num_delay_crash_threads == 0: 471 # The inferior process should have exited without crashing 472 self.assertEqual(0, seen_crashed_threads, "Unexpected thread(s) in crashed state") 473 self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) 474 475 # Verify the number of actions took place matches expected numbers 476 self.assertEqual(num_delay_breakpoint_threads + num_breakpoint_threads, seen_breakpoint_threads) 477 self.assertEqual(num_delay_signal_threads + num_signal_threads, seen_signal_threads) 478 self.assertEqual(num_delay_watchpoint_threads + num_watchpoint_threads, seen_watchpoint_threads) 479 480 481if __name__ == '__main__': 482 import atexit 483 lldb.SBDebugger.Initialize() 484 atexit.register(lambda: lldb.SBDebugger.Terminate()) 485 unittest2.main() 486