1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/threading/thread.h" 6 7#include <stddef.h> 8#include <stdint.h> 9 10#include <vector> 11 12#include "base/bind.h" 13#include "base/debug/leak_annotations.h" 14#include "base/macros.h" 15#include "base/memory/ptr_util.h" 16#include "base/message_loop/message_loop.h" 17#include "base/run_loop.h" 18#include "base/single_thread_task_runner.h" 19#include "base/synchronization/waitable_event.h" 20#include "base/test/gtest_util.h" 21#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 22#include "base/threading/platform_thread.h" 23#include "base/time/time.h" 24#include "build/build_config.h" 25#include "testing/gtest/include/gtest/gtest.h" 26#include "testing/platform_test.h" 27 28using base::Thread; 29 30typedef PlatformTest ThreadTest; 31 32namespace { 33 34void ToggleValue(bool* value) { 35 ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean " 36 "in base/thread_unittest"); 37 *value = !*value; 38} 39 40class SleepInsideInitThread : public Thread { 41 public: 42 SleepInsideInitThread() : Thread("none") { 43 init_called_ = false; 44 ANNOTATE_BENIGN_RACE( 45 this, "Benign test-only data race on vptr - http://crbug.com/98219"); 46 } 47 ~SleepInsideInitThread() override { Stop(); } 48 49 void Init() override { 50 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500)); 51 init_called_ = true; 52 } 53 bool InitCalled() { return init_called_; } 54 55 private: 56 bool init_called_; 57 58 DISALLOW_COPY_AND_ASSIGN(SleepInsideInitThread); 59}; 60 61enum ThreadEvent { 62 // Thread::Init() was called. 63 THREAD_EVENT_INIT = 0, 64 65 // The MessageLoop for the thread was deleted. 66 THREAD_EVENT_MESSAGE_LOOP_DESTROYED, 67 68 // Thread::CleanUp() was called. 69 THREAD_EVENT_CLEANUP, 70 71 // Keep at end of list. 72 THREAD_NUM_EVENTS 73}; 74 75typedef std::vector<ThreadEvent> EventList; 76 77class CaptureToEventList : public Thread { 78 public: 79 // This Thread pushes events into the vector |event_list| to show 80 // the order they occured in. |event_list| must remain valid for the 81 // lifetime of this thread. 82 explicit CaptureToEventList(EventList* event_list) 83 : Thread("none"), 84 event_list_(event_list) { 85 } 86 87 ~CaptureToEventList() override { Stop(); } 88 89 void Init() override { event_list_->push_back(THREAD_EVENT_INIT); } 90 91 void CleanUp() override { event_list_->push_back(THREAD_EVENT_CLEANUP); } 92 93 private: 94 EventList* event_list_; 95 96 DISALLOW_COPY_AND_ASSIGN(CaptureToEventList); 97}; 98 99// Observer that writes a value into |event_list| when a message loop has been 100// destroyed. 101class CapturingDestructionObserver 102 : public base::MessageLoop::DestructionObserver { 103 public: 104 // |event_list| must remain valid throughout the observer's lifetime. 105 explicit CapturingDestructionObserver(EventList* event_list) 106 : event_list_(event_list) { 107 } 108 109 // DestructionObserver implementation: 110 void WillDestroyCurrentMessageLoop() override { 111 event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED); 112 event_list_ = NULL; 113 } 114 115 private: 116 EventList* event_list_; 117 118 DISALLOW_COPY_AND_ASSIGN(CapturingDestructionObserver); 119}; 120 121// Task that adds a destruction observer to the current message loop. 122void RegisterDestructionObserver( 123 base::MessageLoop::DestructionObserver* observer) { 124 base::MessageLoop::current()->AddDestructionObserver(observer); 125} 126 127// Task that calls GetThreadId() of |thread|, stores the result into |id|, then 128// signal |event|. 129void ReturnThreadId(base::Thread* thread, 130 base::PlatformThreadId* id, 131 base::WaitableEvent* event) { 132 *id = thread->GetThreadId(); 133 event->Signal(); 134} 135 136} // namespace 137 138TEST_F(ThreadTest, StartWithOptions_StackSize) { 139 Thread a("StartWithStackSize"); 140 // Ensure that the thread can work with only 12 kb and still process a 141 // message. At the same time, we should scale with the bitness of the system 142 // where 12 kb is definitely not enough. 143 // 12 kb = 3072 Slots on a 32-bit system, so we'll scale based off of that. 144 Thread::Options options; 145#if defined(ADDRESS_SANITIZER) || !defined(NDEBUG) 146 // ASan bloats the stack variables and overflows the 3072 slot stack. Some 147 // debug builds also grow the stack too much. 148 options.stack_size = 2 * 3072 * sizeof(uintptr_t); 149#else 150 options.stack_size = 3072 * sizeof(uintptr_t); 151#endif 152 EXPECT_TRUE(a.StartWithOptions(options)); 153 EXPECT_TRUE(a.message_loop()); 154 EXPECT_TRUE(a.IsRunning()); 155 156 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, 157 base::WaitableEvent::InitialState::NOT_SIGNALED); 158 a.task_runner()->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal, 159 base::Unretained(&event))); 160 event.Wait(); 161} 162 163// Intentional test-only race for otherwise untestable code, won't fix. 164// https://crbug.com/634383 165#if !defined(THREAD_SANITIZER) 166TEST_F(ThreadTest, StartWithOptions_NonJoinable) { 167 Thread* a = new Thread("StartNonJoinable"); 168 // Non-joinable threads have to be leaked for now (see 169 // Thread::Options::joinable for details). 170 ANNOTATE_LEAKING_OBJECT_PTR(a); 171 172 Thread::Options options; 173 options.joinable = false; 174 EXPECT_TRUE(a->StartWithOptions(options)); 175 EXPECT_TRUE(a->message_loop()); 176 EXPECT_TRUE(a->IsRunning()); 177 178 // Without this call this test is racy. The above IsRunning() succeeds because 179 // of an early-return condition while between Start() and StopSoon(), after 180 // invoking StopSoon() below this early-return condition is no longer 181 // satisfied and the real |is_running_| bit has to be checked. It could still 182 // be false if the message loop hasn't started for real in practice. This is 183 // only a requirement for this test because the non-joinable property forces 184 // it to use StopSoon() and not wait for a complete Stop(). 185 EXPECT_TRUE(a->WaitUntilThreadStarted()); 186 187 // Make the thread block until |block_event| is signaled. 188 base::WaitableEvent block_event( 189 base::WaitableEvent::ResetPolicy::AUTOMATIC, 190 base::WaitableEvent::InitialState::NOT_SIGNALED); 191 a->task_runner()->PostTask( 192 FROM_HERE, 193 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&block_event))); 194 195 a->StopSoon(); 196 EXPECT_TRUE(a->IsRunning()); 197 198 // Unblock the task and give a bit of extra time to unwind QuitWhenIdle(). 199 block_event.Signal(); 200 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); 201 202 // The thread should now have stopped on its own. 203 EXPECT_FALSE(a->IsRunning()); 204} 205#endif 206 207TEST_F(ThreadTest, TwoTasksOnJoinableThread) { 208 bool was_invoked = false; 209 { 210 Thread a("TwoTasksOnJoinableThread"); 211 EXPECT_TRUE(a.Start()); 212 EXPECT_TRUE(a.message_loop()); 213 214 // Test that all events are dispatched before the Thread object is 215 // destroyed. We do this by dispatching a sleep event before the 216 // event that will toggle our sentinel value. 217 a.task_runner()->PostTask( 218 FROM_HERE, base::Bind(static_cast<void (*)(base::TimeDelta)>( 219 &base::PlatformThread::Sleep), 220 base::TimeDelta::FromMilliseconds(20))); 221 a.task_runner()->PostTask(FROM_HERE, 222 base::Bind(&ToggleValue, &was_invoked)); 223 } 224 EXPECT_TRUE(was_invoked); 225} 226 227TEST_F(ThreadTest, DestroyWhileRunningIsSafe) { 228 Thread a("DestroyWhileRunningIsSafe"); 229 EXPECT_TRUE(a.Start()); 230 EXPECT_TRUE(a.WaitUntilThreadStarted()); 231} 232 233// TODO(gab): Enable this test when destroying a non-joinable Thread instance 234// is supported (proposal @ https://crbug.com/629139#c14). 235TEST_F(ThreadTest, DISABLED_DestroyWhileRunningNonJoinableIsSafe) { 236 { 237 Thread a("DestroyWhileRunningNonJoinableIsSafe"); 238 Thread::Options options; 239 options.joinable = false; 240 EXPECT_TRUE(a.StartWithOptions(options)); 241 EXPECT_TRUE(a.WaitUntilThreadStarted()); 242 } 243 244 // Attempt to catch use-after-frees from the non-joinable thread in the 245 // scope of this test if any. 246 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); 247} 248 249TEST_F(ThreadTest, StopSoon) { 250 Thread a("StopSoon"); 251 EXPECT_TRUE(a.Start()); 252 EXPECT_TRUE(a.message_loop()); 253 EXPECT_TRUE(a.IsRunning()); 254 a.StopSoon(); 255 a.Stop(); 256 EXPECT_FALSE(a.message_loop()); 257 EXPECT_FALSE(a.IsRunning()); 258} 259 260TEST_F(ThreadTest, StopTwiceNop) { 261 Thread a("StopTwiceNop"); 262 EXPECT_TRUE(a.Start()); 263 EXPECT_TRUE(a.message_loop()); 264 EXPECT_TRUE(a.IsRunning()); 265 a.StopSoon(); 266 // Calling StopSoon() a second time should be a nop. 267 a.StopSoon(); 268 a.Stop(); 269 // Same with Stop(). 270 a.Stop(); 271 EXPECT_FALSE(a.message_loop()); 272 EXPECT_FALSE(a.IsRunning()); 273 // Calling them when not running should also nop. 274 a.StopSoon(); 275 a.Stop(); 276} 277 278// TODO(gab): Enable this test in conjunction with re-enabling the sequence 279// check in Thread::Stop() as part of http://crbug.com/629139. 280TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) { 281 Thread a("StopOnNonOwningThreadDeath"); 282 EXPECT_TRUE(a.StartAndWaitForTesting()); 283 284 Thread b("NonOwningThread"); 285 b.Start(); 286 EXPECT_DCHECK_DEATH({ 287 // Stopping |a| on |b| isn't allowed. 288 b.task_runner()->PostTask(FROM_HERE, 289 base::Bind(&Thread::Stop, base::Unretained(&a))); 290 // Block here so the DCHECK on |b| always happens in this scope. 291 base::PlatformThread::Sleep(base::TimeDelta::Max()); 292 }); 293} 294 295TEST_F(ThreadTest, TransferOwnershipAndStop) { 296 std::unique_ptr<Thread> a = 297 base::MakeUnique<Thread>("TransferOwnershipAndStop"); 298 EXPECT_TRUE(a->StartAndWaitForTesting()); 299 EXPECT_TRUE(a->IsRunning()); 300 301 Thread b("TakingOwnershipThread"); 302 b.Start(); 303 304 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, 305 base::WaitableEvent::InitialState::NOT_SIGNALED); 306 307 // a->DetachFromSequence() should allow |b| to use |a|'s Thread API. 308 a->DetachFromSequence(); 309 b.task_runner()->PostTask( 310 FROM_HERE, base::Bind( 311 [](std::unique_ptr<Thread> thread_to_stop, 312 base::WaitableEvent* event_to_signal) -> void { 313 thread_to_stop->Stop(); 314 event_to_signal->Signal(); 315 }, 316 base::Passed(&a), base::Unretained(&event))); 317 318 event.Wait(); 319} 320 321TEST_F(ThreadTest, StartTwice) { 322 Thread a("StartTwice"); 323 324 EXPECT_FALSE(a.message_loop()); 325 EXPECT_FALSE(a.IsRunning()); 326 327 EXPECT_TRUE(a.Start()); 328 EXPECT_TRUE(a.message_loop()); 329 EXPECT_TRUE(a.IsRunning()); 330 331 a.Stop(); 332 EXPECT_FALSE(a.message_loop()); 333 EXPECT_FALSE(a.IsRunning()); 334 335 EXPECT_TRUE(a.Start()); 336 EXPECT_TRUE(a.message_loop()); 337 EXPECT_TRUE(a.IsRunning()); 338 339 a.Stop(); 340 EXPECT_FALSE(a.message_loop()); 341 EXPECT_FALSE(a.IsRunning()); 342} 343 344// Intentional test-only race for otherwise untestable code, won't fix. 345// https://crbug.com/634383 346#if !defined(THREAD_SANITIZER) 347TEST_F(ThreadTest, StartTwiceNonJoinableNotAllowed) { 348 LOG(ERROR) << __FUNCTION__; 349 Thread* a = new Thread("StartTwiceNonJoinable"); 350 // Non-joinable threads have to be leaked for now (see 351 // Thread::Options::joinable for details). 352 ANNOTATE_LEAKING_OBJECT_PTR(a); 353 354 Thread::Options options; 355 options.joinable = false; 356 EXPECT_TRUE(a->StartWithOptions(options)); 357 EXPECT_TRUE(a->message_loop()); 358 EXPECT_TRUE(a->IsRunning()); 359 360 // Signaled when last task on |a| is processed. 361 base::WaitableEvent last_task_event( 362 base::WaitableEvent::ResetPolicy::AUTOMATIC, 363 base::WaitableEvent::InitialState::NOT_SIGNALED); 364 a->task_runner()->PostTask(FROM_HERE, 365 base::Bind(&base::WaitableEvent::Signal, 366 base::Unretained(&last_task_event))); 367 368 // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be 369 // processed and a little more for QuitWhenIdle() to unwind before considering 370 // the thread "stopped". 371 a->StopSoon(); 372 base::PlatformThread::YieldCurrentThread(); 373 last_task_event.Wait(); 374 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); 375 376 // This test assumes that the above was sufficient to let the thread fully 377 // stop. 378 ASSERT_FALSE(a->IsRunning()); 379 380 // Restarting it should not be allowed. 381 EXPECT_DCHECK_DEATH(a->Start()); 382} 383#endif 384 385TEST_F(ThreadTest, ThreadName) { 386 Thread a("ThreadName"); 387 EXPECT_TRUE(a.Start()); 388 EXPECT_EQ("ThreadName", a.thread_name()); 389} 390 391TEST_F(ThreadTest, ThreadId) { 392 Thread a("ThreadId0"); 393 Thread b("ThreadId1"); 394 a.Start(); 395 b.Start(); 396 397 // Post a task that calls GetThreadId() on the created thread. 398 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, 399 base::WaitableEvent::InitialState::NOT_SIGNALED); 400 base::PlatformThreadId id_from_new_thread; 401 a.task_runner()->PostTask( 402 FROM_HERE, base::Bind(ReturnThreadId, &a, &id_from_new_thread, &event)); 403 404 // Call GetThreadId() on the current thread before calling event.Wait() so 405 // that this test can find a race issue with TSAN. 406 base::PlatformThreadId id_from_current_thread = a.GetThreadId(); 407 408 // Check if GetThreadId() returns consistent value in both threads. 409 event.Wait(); 410 EXPECT_EQ(id_from_current_thread, id_from_new_thread); 411 412 // A started thread should have a valid ID. 413 EXPECT_NE(base::kInvalidThreadId, a.GetThreadId()); 414 EXPECT_NE(base::kInvalidThreadId, b.GetThreadId()); 415 416 // Each thread should have a different thread ID. 417 EXPECT_NE(a.GetThreadId(), b.GetThreadId()); 418} 419 420TEST_F(ThreadTest, ThreadIdWithRestart) { 421 Thread a("ThreadIdWithRestart"); 422 base::PlatformThreadId previous_id = base::kInvalidThreadId; 423 424 for (size_t i = 0; i < 16; ++i) { 425 EXPECT_TRUE(a.Start()); 426 base::PlatformThreadId current_id = a.GetThreadId(); 427 EXPECT_NE(previous_id, current_id); 428 previous_id = current_id; 429 a.Stop(); 430 } 431} 432 433// Make sure Init() is called after Start() and before 434// WaitUntilThreadInitialized() returns. 435TEST_F(ThreadTest, SleepInsideInit) { 436 SleepInsideInitThread t; 437 EXPECT_FALSE(t.InitCalled()); 438 t.StartAndWaitForTesting(); 439 EXPECT_TRUE(t.InitCalled()); 440} 441 442// Make sure that the destruction sequence is: 443// 444// (1) Thread::CleanUp() 445// (2) MessageLoop::~MessageLoop() 446// MessageLoop::DestructionObservers called. 447TEST_F(ThreadTest, CleanUp) { 448 EventList captured_events; 449 CapturingDestructionObserver loop_destruction_observer(&captured_events); 450 451 { 452 // Start a thread which writes its event into |captured_events|. 453 CaptureToEventList t(&captured_events); 454 EXPECT_TRUE(t.Start()); 455 EXPECT_TRUE(t.message_loop()); 456 EXPECT_TRUE(t.IsRunning()); 457 458 // Register an observer that writes into |captured_events| once the 459 // thread's message loop is destroyed. 460 t.task_runner()->PostTask( 461 FROM_HERE, base::Bind(&RegisterDestructionObserver, 462 base::Unretained(&loop_destruction_observer))); 463 464 // Upon leaving this scope, the thread is deleted. 465 } 466 467 // Check the order of events during shutdown. 468 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size()); 469 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]); 470 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); 471 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); 472} 473 474TEST_F(ThreadTest, ThreadNotStarted) { 475 Thread a("Inert"); 476 EXPECT_FALSE(a.task_runner()); 477} 478 479TEST_F(ThreadTest, MultipleWaitUntilThreadStarted) { 480 Thread a("MultipleWaitUntilThreadStarted"); 481 EXPECT_TRUE(a.Start()); 482 // It's OK to call WaitUntilThreadStarted() multiple times. 483 EXPECT_TRUE(a.WaitUntilThreadStarted()); 484 EXPECT_TRUE(a.WaitUntilThreadStarted()); 485} 486 487TEST_F(ThreadTest, FlushForTesting) { 488 Thread a("FlushForTesting"); 489 490 // Flushing a non-running thread should be a no-op. 491 a.FlushForTesting(); 492 493 ASSERT_TRUE(a.Start()); 494 495 // Flushing a thread with no tasks shouldn't block. 496 a.FlushForTesting(); 497 498 constexpr base::TimeDelta kSleepPerTestTask = 499 base::TimeDelta::FromMilliseconds(50); 500 constexpr size_t kNumSleepTasks = 5; 501 502 const base::TimeTicks ticks_before_post = base::TimeTicks::Now(); 503 504 for (size_t i = 0; i < kNumSleepTasks; ++i) { 505 a.task_runner()->PostTask( 506 FROM_HERE, base::Bind(&base::PlatformThread::Sleep, kSleepPerTestTask)); 507 } 508 509 // All tasks should have executed, as reflected by the elapsed time. 510 a.FlushForTesting(); 511 EXPECT_GE(base::TimeTicks::Now() - ticks_before_post, 512 kNumSleepTasks * kSleepPerTestTask); 513 514 a.Stop(); 515 516 // Flushing a stopped thread should be a no-op. 517 a.FlushForTesting(); 518} 519 520namespace { 521 522// A Thread which uses a MessageLoop on the stack. It won't start a real 523// underlying thread (instead its messages can be processed by a RunLoop on the 524// stack). 525class ExternalMessageLoopThread : public Thread { 526 public: 527 ExternalMessageLoopThread() : Thread("ExternalMessageLoopThread") {} 528 529 ~ExternalMessageLoopThread() override { Stop(); } 530 531 void InstallMessageLoop() { SetMessageLoop(&external_message_loop_); } 532 533 void VerifyUsingExternalMessageLoop( 534 bool expected_using_external_message_loop) { 535 EXPECT_EQ(expected_using_external_message_loop, 536 using_external_message_loop()); 537 } 538 539 private: 540 base::MessageLoop external_message_loop_; 541 542 DISALLOW_COPY_AND_ASSIGN(ExternalMessageLoopThread); 543}; 544 545} // namespace 546 547TEST_F(ThreadTest, ExternalMessageLoop) { 548 ExternalMessageLoopThread a; 549 EXPECT_FALSE(a.message_loop()); 550 EXPECT_FALSE(a.IsRunning()); 551 a.VerifyUsingExternalMessageLoop(false); 552 553 a.InstallMessageLoop(); 554 EXPECT_TRUE(a.message_loop()); 555 EXPECT_TRUE(a.IsRunning()); 556 a.VerifyUsingExternalMessageLoop(true); 557 558 bool ran = false; 559 a.task_runner()->PostTask( 560 FROM_HERE, base::Bind([](bool* toggled) { *toggled = true; }, &ran)); 561 base::RunLoop().RunUntilIdle(); 562 EXPECT_TRUE(ran); 563 564 a.Stop(); 565 EXPECT_FALSE(a.message_loop()); 566 EXPECT_FALSE(a.IsRunning()); 567 a.VerifyUsingExternalMessageLoop(true); 568 569 // Confirm that running any remaining tasks posted from Stop() goes smoothly 570 // (e.g. https://codereview.chromium.org/2135413003/#ps300001 crashed if 571 // StopSoon() posted Thread::ThreadQuitHelper() while |run_loop_| was null). 572 base::RunLoop().RunUntilIdle(); 573} 574