| 589 | } |
| 590 | |
| 591 | Status Thread::StartThread(string category, string name, |
| 592 | std::function<void()> functor, uint64_t flags, |
| 593 | scoped_refptr<Thread>* holder) { |
| 594 | TRACE_COUNTER_INCREMENT("threads_started", 1); |
| 595 | TRACE_COUNTER_SCOPE_LATENCY_US("thread_start_us"); |
| 596 | GoogleOnceInit(&once, &InitThreading); |
| 597 | |
| 598 | const string log_prefix = Substitute("$0 ($1) ", name, category); |
| 599 | SCOPED_LOG_SLOW_EXECUTION_PREFIX(WARNING, 500 /* ms */, log_prefix, "starting thread"); |
| 600 | |
| 601 | // Temporary reference for the duration of this function. |
| 602 | scoped_refptr<Thread> t(new Thread( |
| 603 | std::move(category), std::move(name), std::move(functor))); |
| 604 | |
| 605 | // Optional, and only set if the thread was successfully created. |
| 606 | // |
| 607 | // We have to set this before we even start the thread because it's |
| 608 | // allowed for the thread functor to access 'holder'. |
| 609 | if (holder) { |
| 610 | *holder = t; |
| 611 | } |
| 612 | |
| 613 | t->tid_ = PARENT_WAITING_TID; |
| 614 | |
| 615 | // Add a reference count to the thread since SuperviseThread() needs to |
| 616 | // access the thread object, and we have no guarantee that our caller |
| 617 | // won't drop the reference as soon as we return. This is dereferenced |
| 618 | // in FinishThread(). |
| 619 | t->AddRef(); |
| 620 | |
| 621 | auto cleanup = MakeScopedCleanup([&]() { |
| 622 | // If we failed to create the thread, we need to undo all of our prep work. |
| 623 | t->tid_ = INVALID_TID; |
| 624 | t->Release(); |
| 625 | }); |
| 626 | |
| 627 | if (PREDICT_FALSE(FLAGS_thread_inject_start_latency_ms > 0)) { |
| 628 | LOG(INFO) << "Injecting " << FLAGS_thread_inject_start_latency_ms << "ms sleep on thread start"; |
| 629 | SleepFor(MonoDelta::FromMilliseconds(FLAGS_thread_inject_start_latency_ms)); |
| 630 | } |
| 631 | |
| 632 | { |
| 633 | SCOPED_LOG_SLOW_EXECUTION_PREFIX(WARNING, 500 /* ms */, log_prefix, "creating pthread"); |
| 634 | SCOPED_WATCH_STACK((flags & NO_STACK_WATCHDOG) ? 0 : 250); |
| 635 | int ret = pthread_create(&t->thread_, nullptr, &Thread::SuperviseThread, t.get()); |
| 636 | if (ret) { |
| 637 | string msg; |
| 638 | if (ret == EAGAIN) { |
| 639 | uint64_t rlimit_nproc = Env::Default()->GetResourceLimit( |
| 640 | Env::ResourceLimitType::RUNNING_THREADS_PER_EUID); |
| 641 | uint64_t num_threads = thread_manager->ReadThreadsRunning(); |
| 642 | msg = Substitute(" ($0 Kudu-managed threads running in this process, " |
| 643 | "$1 max processes allowed for current user)", |
| 644 | num_threads, rlimit_nproc); |
| 645 | } |
| 646 | return Status::RuntimeError(Substitute("Could not create thread$0", msg), strerror(ret), ret); |
| 647 | } |
| 648 | } |
nothing calls this directly
no test coverage detected