From a3689a8b6c0655df21f98e7e34df11aeb4eb22ee Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 25 Oct 2019 11:49:03 -0700 Subject: [PATCH] Properly handle race at thread creation --- src/cpp/thread_manager/thread_manager.cc | 20 ++++++++++++++++---- src/cpp/thread_manager/thread_manager.h | 4 ++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 2b65352f797..b633598660d 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -34,8 +34,10 @@ ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr) thd_ = grpc_core::Thread( "grpcpp_sync_server", [](void* th) { static_cast(th)->Run(); }, - this); - thd_.Start(); + this, &created_); + if (!created_) { + gpr_log(GPR_ERROR, "Could not create grpc_sync_server worker-thread"); + } } void ThreadManager::WorkerThread::Run() { @@ -139,7 +141,9 @@ void ThreadManager::Initialize() { } for (int i = 0; i < min_pollers_; i++) { - new WorkerThread(this); + WorkerThread* worker = new WorkerThread(this); + GPR_ASSERT(worker->created()); // Must be able to create the minimum + worker->Start(); } } @@ -177,7 +181,15 @@ void ThreadManager::MainWorkLoop() { } // Drop lock before spawning thread to avoid contention lock.Unlock(); - new WorkerThread(this); + WorkerThread* worker = new WorkerThread(this); + if (worker->created()) { + worker->Start(); + } else { + num_pollers_--; + num_threads_--; + resource_exhausted = true; + delete worker; + } } else if (num_pollers_ > 0) { // There is still at least some thread polling, so we can go on // even though we are below the number of pollers that we would diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 4c1b3aad2b4..f275e6ff9d3 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -124,6 +124,9 @@ class ThreadManager { WorkerThread(ThreadManager* thd_mgr); ~WorkerThread(); + bool created() const { return created_; } + void Start() { thd_.Start(); } + private: // Calls thd_mgr_->MainWorkLoop() and once that completes, calls // thd_mgr_>MarkAsCompleted(this) to mark the thread as completed @@ -131,6 +134,7 @@ class ThreadManager { ThreadManager* const thd_mgr_; grpc_core::Thread thd_; + bool created_; }; // The main function in ThreadManager