From ef0e64cdf5350995e16bf36b50dd7efb094a4a25 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Nov 2017 07:50:37 +0100 Subject: Revert "Revert "Switching from UNAUTHENTICATED to UNAVAILABLE for auth metadata failure"" --- test/cpp/end2end/end2end_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 4c8dfe0f40..a6ea5aada9 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -1609,7 +1609,7 @@ TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { Status s = stub_->Echo(&context, request, &response); EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); } TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { @@ -1626,7 +1626,7 @@ TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { Status s = stub_->Echo(&context, request, &response); EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); } TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { @@ -1644,7 +1644,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { Status s = stub_->Echo(&context, request, &response); EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); EXPECT_EQ(s.error_message(), grpc::string("Getting metadata from plugin failed with error: ") + kTestCredsPluginErrorMsg); @@ -1705,7 +1705,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { Status s = stub_->Echo(&context, request, &response); EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); EXPECT_EQ(s.error_message(), grpc::string("Getting metadata from plugin failed with error: ") + kTestCredsPluginErrorMsg); -- cgit v1.2.3 From 5dd32268be62114e8a7c81d60c0dc2633fb83081 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 14 Nov 2017 19:04:02 -0800 Subject: Switch C++ sync server to use gpr_thd rather than std::thread and provide resource exhaustion mechanism --- include/grpc++/impl/codegen/completion_queue.h | 6 +- include/grpc++/impl/codegen/method_handler_impl.h | 12 +- include/grpc++/impl/codegen/server_context.h | 6 +- include/grpc++/server.h | 18 ++- include/grpc++/server_builder.h | 19 +++ src/cpp/client/secure_credentials.cc | 14 +- src/cpp/server/create_default_thread_pool.cc | 2 +- src/cpp/server/dynamic_thread_pool.cc | 54 ++++++-- src/cpp/server/dynamic_thread_pool.h | 20 ++- src/cpp/server/secure_server_credentials.cc | 7 +- src/cpp/server/server_builder.cc | 7 +- src/cpp/server/server_cc.cc | 46 +++++-- src/cpp/server/thread_pool_interface.h | 4 +- src/cpp/thread_manager/thread_manager.cc | 54 ++++++-- src/cpp/thread_manager/thread_manager.h | 28 +++- test/cpp/end2end/thread_stress_test.cc | 157 +++++++++++++--------- test/cpp/thread_manager/BUILD | 31 +++++ test/cpp/thread_manager/thread_manager_test.cc | 8 +- 18 files changed, 361 insertions(+), 132 deletions(-) create mode 100644 test/cpp/thread_manager/BUILD (limited to 'test') diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index b8a7862578..452eac6646 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -78,7 +78,8 @@ template class ServerStreamingHandler; template class BidiStreamingHandler; -class UnknownMethodHandler; +template +class ErrorMethodHandler; template class TemplatedBidiStreamingHandler; template @@ -221,7 +222,8 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::ServerStreamingHandler; template friend class ::grpc::internal::TemplatedBidiStreamingHandler; - friend class ::grpc::internal::UnknownMethodHandler; + template + friend class ::grpc::internal::ErrorMethodHandler; friend class ::grpc::Server; friend class ::grpc::ServerContext; friend class ::grpc::ServerInterface; diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index c0af4ca130..d98ab7938c 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -242,12 +242,14 @@ class SplitServerStreamingHandler ServerSplitStreamer, false>(func) {} }; -/// Handle unknown method by returning UNIMPLEMENTED error. -class UnknownMethodHandler : public MethodHandler { +/// General method handler class for errors that prevent real method use +/// e.g., handle unknown method by returning UNIMPLEMENTED error. +template +class ErrorMethodHandler : public MethodHandler { public: template static void FillOps(ServerContext* context, T* ops) { - Status status(StatusCode::UNIMPLEMENTED, ""); + Status status(code, ""); if (!context->sent_initial_metadata_) { ops->SendInitialMetadata(context->initial_metadata_, context->initial_metadata_flags()); @@ -267,6 +269,10 @@ class UnknownMethodHandler : public MethodHandler { } }; +typedef ErrorMethodHandler UnknownMethodHandler; +typedef ErrorMethodHandler + ResourceExhaustedHandler; + } // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index a2d6967bf8..9f20335a2a 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -63,7 +63,8 @@ template class ServerStreamingHandler; template class BidiStreamingHandler; -class UnknownMethodHandler; +template +class ErrorMethodHandler; template class TemplatedBidiStreamingHandler; class Call; @@ -255,7 +256,8 @@ class ServerContext { friend class ::grpc::internal::ServerStreamingHandler; template friend class ::grpc::internal::TemplatedBidiStreamingHandler; - friend class ::grpc::internal::UnknownMethodHandler; + template + friend class ::grpc::internal::ErrorMethodHandler; friend class ::grpc::ClientContext; /// Prevent copying. diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 01c4a60d21..456603e4e7 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -35,6 +35,7 @@ #include #include #include +#include struct grpc_server; @@ -138,10 +139,17 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on /// server completion queues passed via sync_server_cqs param. + /// + /// \param thread_creator The thread creation function for the sync + /// server. Typically gpr_thd_new Server(int max_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec); + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + std::function + thread_creator, + std::function thread_joiner); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the Server instance. @@ -220,6 +228,14 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { std::unique_ptr health_check_service_; bool health_check_service_disabled_; + + std::function + thread_creator_; + std::function thread_joiner_; + + // A special handler for resource exhausted in sync case + std::unique_ptr resource_exhausted_handler_; }; } // namespace grpc diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index e2bae4b41f..25bbacbbc7 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -20,6 +20,7 @@ #define GRPCXX_SERVER_BUILDER_H #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include @@ -47,6 +49,7 @@ class Service; namespace testing { class ServerBuilderPluginTest; +class ServerBuilderThreadCreatorOverrideTest; } // namespace testing /// A builder class for the creation and startup of \a grpc::Server instances. @@ -213,6 +216,17 @@ class ServerBuilder { private: friend class ::grpc::testing::ServerBuilderPluginTest; + friend class ::grpc::testing::ServerBuilderThreadCreatorOverrideTest; + + ServerBuilder& SetThreadFunctions( + std::function + thread_creator, + std::function thread_joiner) { + thread_creator_ = thread_creator; + thread_joiner_ = thread_joiner; + return *this; + } struct Port { grpc::string addr; @@ -272,6 +286,11 @@ class ServerBuilder { grpc_compression_algorithm algorithm; } maybe_default_compression_algorithm_; uint32_t enabled_compression_algorithms_bitset_; + + std::function + thread_creator_; + std::function thread_joiner_; }; } // namespace grpc diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index 4fb128d98b..94519d817b 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -189,10 +189,16 @@ int MetadataCredentialsPluginWrapper::GetMetadata( } if (w->plugin_->IsBlocking()) { // Asynchronous return. - w->thread_pool_->Add( - std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context, - cb, user_data, nullptr, nullptr, nullptr, nullptr)); - return 0; + if (w->thread_pool_->Add(std::bind( + &MetadataCredentialsPluginWrapper::InvokePlugin, w, context, cb, + user_data, nullptr, nullptr, nullptr, nullptr))) { + return 0; + } else { + *num_creds_md = 0; + *status = GRPC_STATUS_RESOURCE_EXHAUSTED; + *error_details = nullptr; + return true; + } } else { // Synchronous return. w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status, diff --git a/src/cpp/server/create_default_thread_pool.cc b/src/cpp/server/create_default_thread_pool.cc index 8ca3e32c2f..2d2abbe9d1 100644 --- a/src/cpp/server/create_default_thread_pool.cc +++ b/src/cpp/server/create_default_thread_pool.cc @@ -28,7 +28,7 @@ namespace { ThreadPoolInterface* CreateDefaultThreadPoolImpl() { int cores = gpr_cpu_num_cores(); if (!cores) cores = 4; - return new DynamicThreadPool(cores); + return new DynamicThreadPool(cores, gpr_thd_new, gpr_thd_join); } CreateThreadPoolFunc g_ctp_impl = CreateDefaultThreadPoolImpl; diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index 81c78fe739..d0e62313f6 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -19,19 +19,32 @@ #include "src/cpp/server/dynamic_thread_pool.h" #include -#include #include +#include namespace grpc { -DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool) - : pool_(pool), - thd_(new std::thread(&DynamicThreadPool::DynamicThread::ThreadFunc, - this)) {} +DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool, + bool* valid) + : pool_(pool) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + + std::lock_guard l(dt_mu_); + valid_ = *valid = pool->thread_creator_( + &thd_, "dynamic thread", + [](void* th) { + reinterpret_cast(th)->ThreadFunc(); + }, + this, &opt); +} + DynamicThreadPool::DynamicThread::~DynamicThread() { - thd_->join(); - thd_.reset(); + std::lock_guard l(dt_mu_); + if (valid_) { + pool_->thread_joiner_(thd_); + } } void DynamicThreadPool::DynamicThread::ThreadFunc() { @@ -73,15 +86,26 @@ void DynamicThreadPool::ThreadFunc() { } } -DynamicThreadPool::DynamicThreadPool(int reserve_threads) +DynamicThreadPool::DynamicThreadPool( + int reserve_threads, + std::function + thread_creator, + std::function thread_joiner) : shutdown_(false), reserve_threads_(reserve_threads), nthreads_(0), - threads_waiting_(0) { + threads_waiting_(0), + thread_creator_(thread_creator), + thread_joiner_(thread_joiner) { for (int i = 0; i < reserve_threads_; i++) { std::lock_guard lock(mu_); nthreads_++; - new DynamicThread(this); + bool valid; + auto* th = new DynamicThread(this, &valid); + if (!valid) { + delete th; + } } } @@ -101,7 +125,7 @@ DynamicThreadPool::~DynamicThreadPool() { ReapThreads(&dead_threads_); } -void DynamicThreadPool::Add(const std::function& callback) { +bool DynamicThreadPool::Add(const std::function& callback) { std::lock_guard lock(mu_); // Add works to the callbacks list callbacks_.push(callback); @@ -109,7 +133,12 @@ void DynamicThreadPool::Add(const std::function& callback) { if (threads_waiting_ == 0) { // Kick off a new thread nthreads_++; - new DynamicThread(this); + bool valid; + auto* th = new DynamicThread(this, &valid); + if (!valid) { + delete th; + return false; + } } else { cv_.notify_one(); } @@ -117,6 +146,7 @@ void DynamicThreadPool::Add(const std::function& callback) { if (!dead_threads_.empty()) { ReapThreads(&dead_threads_); } + return true; } } // namespace grpc diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 9237c6e5ca..75d31cd908 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -24,9 +24,9 @@ #include #include #include -#include #include +#include #include "src/cpp/server/thread_pool_interface.h" @@ -34,20 +34,26 @@ namespace grpc { class DynamicThreadPool final : public ThreadPoolInterface { public: - explicit DynamicThreadPool(int reserve_threads); + DynamicThreadPool(int reserve_threads, + std::function + thread_creator, + std::function thread_joiner); ~DynamicThreadPool(); - void Add(const std::function& callback) override; + bool Add(const std::function& callback) override; private: class DynamicThread { public: - DynamicThread(DynamicThreadPool* pool); + DynamicThread(DynamicThreadPool* pool, bool* valid); ~DynamicThread(); private: DynamicThreadPool* pool_; - std::unique_ptr thd_; + std::mutex dt_mu_; + gpr_thd_id thd_; + bool valid_; void ThreadFunc(); }; std::mutex mu_; @@ -59,6 +65,10 @@ class DynamicThreadPool final : public ThreadPoolInterface { int nthreads_; int threads_waiting_; std::list dead_threads_; + std::function + thread_creator_; + std::function thread_joiner_; void ThreadFunc(); static void ReapThreads(std::list* tlist); diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 0fbe4ccd18..fa08a6200f 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -43,9 +43,14 @@ void AuthMetadataProcessorAyncWrapper::Process( return; } if (w->processor_->IsBlocking()) { - w->thread_pool_->Add( + bool added = w->thread_pool_->Add( std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w, context, md, num_md, cb, user_data)); + if (!added) { + // no thread available, so fail with temporary resource unavailability + cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAVAILABLE, nullptr); + return; + } } else { // invoke directly. w->InvokeProcessor(context, md, num_md, cb, user_data); diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 200e477822..d91ee7f4e3 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "src/cpp/server/thread_pool_interface.h" @@ -43,7 +44,9 @@ ServerBuilder::ServerBuilder() max_send_message_size_(-1), sync_server_settings_(SyncServerSettings()), resource_quota_(nullptr), - generic_service_(nullptr) { + generic_service_(nullptr), + thread_creator_(gpr_thd_new), + thread_joiner_(gpr_thd_join) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); for (auto it = g_plugin_factory_list->begin(); it != g_plugin_factory_list->end(); it++) { @@ -262,7 +265,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { std::unique_ptr server(new Server( max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, - sync_server_settings_.cq_timeout_msec)); + sync_server_settings_.cq_timeout_msec, thread_creator_, thread_joiner_)); if (has_sync_methods) { // This is a Sync server diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 4f8f4e06fc..6ab76a287e 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include "src/core/ext/transport/inproc/inproc_transport.h" #include "src/core/lib/profiling/timers.h" @@ -196,7 +197,8 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { ctx_(mrd->deadline_, &mrd->request_metadata_), has_request_payload_(mrd->has_request_payload_), request_payload_(mrd->request_payload_), - method_(mrd->method_) { + method_(mrd->method_), + server_(server) { ctx_.set_call(mrd->call_); ctx_.cq_ = &cq_; GPR_ASSERT(mrd->in_flight_); @@ -210,10 +212,13 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { } } - void Run(std::shared_ptr global_callbacks) { + void Run(std::shared_ptr global_callbacks, + bool resources) { ctx_.BeginCompletionOp(&call_); global_callbacks->PreSynchronousRequest(&ctx_); - method_->handler()->RunHandler(internal::MethodHandler::HandlerParameter( + auto* handler = resources ? method_->handler() + : server_->resource_exhausted_handler_.get(); + handler->RunHandler(internal::MethodHandler::HandlerParameter( &call_, &ctx_, request_payload_)); global_callbacks->PostSynchronousRequest(&ctx_); request_payload_ = nullptr; @@ -235,6 +240,7 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { const bool has_request_payload_; grpc_byte_buffer* request_payload_; internal::RpcServiceMethod* const method_; + Server* server_; }; private: @@ -255,11 +261,15 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { // appropriate RPC handlers class Server::SyncRequestThreadManager : public ThreadManager { public: - SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, - std::shared_ptr global_callbacks, - int min_pollers, int max_pollers, - int cq_timeout_msec) - : ThreadManager(min_pollers, max_pollers), + SyncRequestThreadManager( + Server* server, CompletionQueue* server_cq, + std::shared_ptr global_callbacks, int min_pollers, + int max_pollers, int cq_timeout_msec, + std::function + thread_creator, + std::function thread_joiner) + : ThreadManager(min_pollers, max_pollers, thread_creator, thread_joiner), server_(server), server_cq_(server_cq), cq_timeout_msec_(cq_timeout_msec), @@ -285,7 +295,7 @@ class Server::SyncRequestThreadManager : public ThreadManager { GPR_UNREACHABLE_CODE(return TIMEOUT); } - void DoWork(void* tag, bool ok) override { + void DoWork(void* tag, bool ok, bool resources) override { SyncRequest* sync_req = static_cast(tag); if (!sync_req) { @@ -305,7 +315,7 @@ class Server::SyncRequestThreadManager : public ThreadManager { } GPR_TIMER_SCOPE("cd.Run()", 0); - cd.Run(global_callbacks_); + cd.Run(global_callbacks_, resources); } // TODO (sreek) If ok is false here (which it isn't in case of // grpc_request_registered_call), we should still re-queue the request @@ -367,7 +377,11 @@ Server::Server( int max_receive_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec) + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + std::function + thread_creator, + std::function thread_joiner) : max_receive_message_size_(max_receive_message_size), sync_server_cqs_(sync_server_cqs), started_(false), @@ -376,7 +390,9 @@ Server::Server( has_generic_service_(false), server_(nullptr), server_initializer_(new ServerInitializer(this)), - health_check_service_disabled_(false) { + health_check_service_disabled_(false), + thread_creator_(thread_creator), + thread_joiner_(thread_joiner) { g_gli_initializer.summon(); gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); global_callbacks_ = g_callbacks; @@ -386,7 +402,7 @@ Server::Server( it++) { sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( this, (*it).get(), global_callbacks_, min_pollers, max_pollers, - sync_cq_timeout_msec)); + sync_cq_timeout_msec, thread_creator_, thread_joiner_)); } grpc_channel_args channel_args; @@ -549,6 +565,10 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { } } + if (!sync_server_cqs_->empty()) { + resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler); + } + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Start(); } diff --git a/src/cpp/server/thread_pool_interface.h b/src/cpp/server/thread_pool_interface.h index 028842a776..656e6673f1 100644 --- a/src/cpp/server/thread_pool_interface.h +++ b/src/cpp/server/thread_pool_interface.h @@ -29,7 +29,9 @@ class ThreadPoolInterface { virtual ~ThreadPoolInterface() {} // Schedule the given callback for execution. - virtual void Add(const std::function& callback) = 0; + // Return true on success, false on failure + virtual bool Add(const std::function& callback) + GRPC_MUST_USE_RESULT = 0; }; // Allows different codebases to use their own thread pool impls diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 23264f1b5b..107c60f4eb 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -20,18 +20,26 @@ #include #include -#include #include +#include namespace grpc { -ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr) +ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr, bool* valid) : thd_mgr_(thd_mgr) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + // Make thread creation exclusive with respect to its join happening in // ~WorkerThread(). std::lock_guard lock(wt_mu_); - thd_ = std::thread(&ThreadManager::WorkerThread::Run, this); + *valid = valid_ = thd_mgr->thread_creator_( + &thd_, "worker thread", + [](void* th) { + reinterpret_cast(th)->Run(); + }, + this, &opt); } void ThreadManager::WorkerThread::Run() { @@ -42,15 +50,24 @@ void ThreadManager::WorkerThread::Run() { ThreadManager::WorkerThread::~WorkerThread() { // Don't join until the thread is fully constructed. std::lock_guard lock(wt_mu_); - thd_.join(); + if (valid_) { + thd_mgr_->thread_joiner_(thd_); + } } -ThreadManager::ThreadManager(int min_pollers, int max_pollers) +ThreadManager::ThreadManager( + int min_pollers, int max_pollers, + std::function + thread_creator, + std::function thread_joiner) : shutdown_(false), num_pollers_(0), min_pollers_(min_pollers), max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers), - num_threads_(0) {} + num_threads_(0), + thread_creator_(thread_creator), + thread_joiner_(thread_joiner) {} ThreadManager::~ThreadManager() { { @@ -111,7 +128,9 @@ void ThreadManager::Initialize() { for (int i = 0; i < min_pollers_; i++) { // Create a new thread (which ends up calling the MainWorkLoop() function - new WorkerThread(this); + bool valid; + new WorkerThread(this, &valid); + GPR_ASSERT(valid); // we need to have at least this minimum } } @@ -138,18 +157,27 @@ void ThreadManager::MainWorkLoop() { case WORK_FOUND: // If we got work and there are now insufficient pollers, start a new // one + bool resources; if (!shutdown_ && num_pollers_ < min_pollers_) { - num_pollers_++; - num_threads_++; + bool valid; // Drop lock before spawning thread to avoid contention lock.unlock(); - new WorkerThread(this); + auto* th = new WorkerThread(this, &valid); + lock.lock(); + if (valid) { + num_pollers_++; + num_threads_++; + } else { + delete th; + } + resources = (num_pollers_ > 0); } else { - // Drop lock for consistency with above branch - lock.unlock(); + resources = true; } + // Drop lock before any application work + lock.unlock(); // Lock is always released at this point - do the application work - DoWork(tag, ok); + DoWork(tag, ok, resources); // Take the lock again to check post conditions lock.lock(); // If we're shutdown, we should finish at this point. diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index a206e0bd8a..4fa8a6c563 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -23,15 +23,19 @@ #include #include #include -#include #include +#include namespace grpc { class ThreadManager { public: - explicit ThreadManager(int min_pollers, int max_pollers); + ThreadManager(int min_pollers, int max_pollers, + std::function + thread_creator, + std::function thread_joiner); virtual ~ThreadManager(); // Initializes and Starts the Rpc Manager threads @@ -50,6 +54,8 @@ class ThreadManager { // - ThreadManager does not interpret the values of 'tag' and 'ok' // - ThreadManager WILL call DoWork() and pass '*tag' and 'ok' as input to // DoWork() + // - ThreadManager will also pass DoWork a bool saying if there are actually + // resources to do the work // // If the return value is SHUTDOWN:, // - ThreadManager WILL NOT call DoWork() and terminates the thead @@ -69,7 +75,7 @@ class ThreadManager { // The implementation of DoWork() should also do any setup needed to ensure // that the next call to PollForWork() (not necessarily by the current thread) // actually finds some work - virtual void DoWork(void* tag, bool ok) = 0; + virtual void DoWork(void* tag, bool ok, bool resources) = 0; // Mark the ThreadManager as shutdown and begin draining the work. This is a // non-blocking call and the caller should call Wait(), a blocking call which @@ -84,15 +90,15 @@ class ThreadManager { virtual void Wait(); private: - // Helper wrapper class around std::thread. This takes a ThreadManager object - // and starts a new std::thread to calls the Run() function. + // Helper wrapper class around thread. This takes a ThreadManager object + // and starts a new thread to calls the Run() function. // // The Run() function calls ThreadManager::MainWorkLoop() function and once // that completes, it marks the WorkerThread completed by calling // ThreadManager::MarkAsCompleted() class WorkerThread { public: - WorkerThread(ThreadManager* thd_mgr); + WorkerThread(ThreadManager* thd_mgr, bool* valid); ~WorkerThread(); private: @@ -102,7 +108,8 @@ class ThreadManager { ThreadManager* const thd_mgr_; std::mutex wt_mu_; - std::thread thd_; + gpr_thd_id thd_; + bool valid_; }; // The main funtion in ThreadManager @@ -129,6 +136,13 @@ class ThreadManager { // currently polling i.e num_pollers_) int num_threads_; + // Functions for creating/joining threads. Normally, these should + // be gpr_thd_new/gpr_thd_join but they are overridable + std::function + thread_creator_; + std::function thread_joiner_; + std::mutex list_mu_; std::list completed_threads_; }; diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 90b2eddbbb..fd43c8f584 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -52,63 +53,13 @@ namespace testing { class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { public: - TestServiceImpl() : signal_client_(false) {} + TestServiceImpl() {} Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { response->set_message(request->message()); return Status::OK; } - - // Unimplemented is left unimplemented to test the returned error. - - Status RequestStream(ServerContext* context, - ServerReader* reader, - EchoResponse* response) override { - EchoRequest request; - response->set_message(""); - while (reader->Read(&request)) { - response->mutable_message()->append(request.message()); - } - return Status::OK; - } - - // Return 3 messages. - // TODO(yangg) make it generic by adding a parameter into EchoRequest - Status ResponseStream(ServerContext* context, const EchoRequest* request, - ServerWriter* writer) override { - EchoResponse response; - response.set_message(request->message() + "0"); - writer->Write(response); - response.set_message(request->message() + "1"); - writer->Write(response); - response.set_message(request->message() + "2"); - writer->Write(response); - - return Status::OK; - } - - Status BidiStream( - ServerContext* context, - ServerReaderWriter* stream) override { - EchoRequest request; - EchoResponse response; - while (stream->Read(&request)) { - gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); - response.set_message(request.message()); - stream->Write(response); - } - return Status::OK; - } - - bool signal_client() { - std::unique_lock lock(mu_); - return signal_client_; - } - - private: - bool signal_client_; - std::mutex mu_; }; template @@ -119,10 +70,15 @@ class CommonStressTest { virtual void SetUp() = 0; virtual void TearDown() = 0; virtual void ResetStub() = 0; + virtual bool AllowExhaustion() = 0; grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); } protected: std::unique_ptr stub_; + // Some tests use a custom thread creator. This should be declared before the + // server so that it's destructor happens after the server + std::unique_ptr creator_; + std::unique_ptr server_; virtual void SetUpStart(ServerBuilder* builder, Service* service) = 0; @@ -147,6 +103,7 @@ class CommonStressTestInsecure : public CommonStressTest { CreateChannel(server_address_.str(), InsecureChannelCredentials()); this->stub_ = grpc::testing::EchoTestService::NewStub(channel); } + bool AllowExhaustion() override { return false; } protected: void SetUpStart(ServerBuilder* builder, Service* service) override { @@ -162,7 +119,7 @@ class CommonStressTestInsecure : public CommonStressTest { std::ostringstream server_address_; }; -template +template class CommonStressTestInproc : public CommonStressTest { public: void ResetStub() override { @@ -170,6 +127,7 @@ class CommonStressTestInproc : public CommonStressTest { std::shared_ptr channel = this->server_->InProcessChannel(args); this->stub_ = grpc::testing::EchoTestService::NewStub(channel); } + bool AllowExhaustion() override { return allow_resource_exhaustion; } protected: void SetUpStart(ServerBuilder* builder, Service* service) override { @@ -194,6 +152,67 @@ class CommonStressTestSyncServer : public BaseClass { TestServiceImpl service_; }; +class ServerBuilderThreadCreatorOverrideTest { + public: + ServerBuilderThreadCreatorOverrideTest(ServerBuilder* builder, size_t limit) + : limit_(limit), threads_(0) { + builder->SetThreadFunctions( + [this](gpr_thd_id* id, const char* name, void (*f)(void*), void* arg, + const gpr_thd_options* options) -> int { + std::unique_lock l(mu_); + if (threads_ < limit_) { + l.unlock(); + if (gpr_thd_new(id, name, f, arg, options) != 0) { + l.lock(); + threads_++; + return 1; + } + } + return 0; + }, + [this](gpr_thd_id id) { + gpr_thd_join(id); + std::unique_lock l(mu_); + threads_--; + if (threads_ == 0) { + done_.notify_one(); + } + }); + } + ~ServerBuilderThreadCreatorOverrideTest() { + // Don't allow destruction until all threads are really done and uncounted + std::unique_lock l(mu_); + done_.wait(l, [this] { return (threads_ == 0); }); + } + + private: + size_t limit_; + size_t threads_; + std::mutex mu_; + std::condition_variable done_; +}; + +template +class CommonStressTestSyncServerLowThreadCount : public BaseClass { + public: + void SetUp() override { + ServerBuilder builder; + this->SetUpStart(&builder, &service_); + builder.SetSyncServerOption(ServerBuilder::SyncServerOption::MIN_POLLERS, + 1); + this->creator_.reset( + new ServerBuilderThreadCreatorOverrideTest(&builder, 4)); + this->SetUpEnd(&builder); + } + void TearDown() override { + this->TearDownStart(); + this->TearDownEnd(); + } + + private: + TestServiceImpl service_; +}; + template class CommonStressTestAsyncServer : public BaseClass { public: @@ -294,7 +313,8 @@ class End2endTest : public ::testing::Test { Common common_; }; -static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs) { +static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, + bool allow_exhaustion, gpr_atm* errors) { EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -302,33 +322,48 @@ static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs) { for (int i = 0; i < num_rpcs; ++i) { ClientContext context; Status s = stub->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok() || (allow_exhaustion && + s.error_code() == StatusCode::RESOURCE_EXHAUSTED)); if (!s.ok()) { - gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), - s.error_message().c_str()); + if (!(allow_exhaustion && + s.error_code() == StatusCode::RESOURCE_EXHAUSTED)) { + gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), + s.error_message().c_str()); + } + gpr_atm_no_barrier_fetch_add(errors, static_cast(1)); + } else { + EXPECT_EQ(response.message(), request.message()); } - ASSERT_TRUE(s.ok()); } } typedef ::testing::Types< CommonStressTestSyncServer>, - CommonStressTestSyncServer>, + CommonStressTestSyncServer>, + CommonStressTestSyncServerLowThreadCount< + CommonStressTestInproc>, CommonStressTestAsyncServer< CommonStressTestInsecure>, - CommonStressTestAsyncServer< - CommonStressTestInproc>> + CommonStressTestAsyncServer>> CommonTypes; TYPED_TEST_CASE(End2endTest, CommonTypes); TYPED_TEST(End2endTest, ThreadStress) { this->common_.ResetStub(); std::vector threads; + gpr_atm errors; + gpr_atm_rel_store(&errors, static_cast(0)); for (int i = 0; i < kNumThreads; ++i) { - threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs); + threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs, + this->common_.AllowExhaustion(), &errors); } for (int i = 0; i < kNumThreads; ++i) { threads[i].join(); } + uint64_t error_cnt = static_cast(gpr_atm_no_barrier_load(&errors)); + if (error_cnt != 0) { + gpr_log(GPR_INFO, "RPC error count: %" PRIu64, error_cnt); + } } template diff --git a/test/cpp/thread_manager/BUILD b/test/cpp/thread_manager/BUILD new file mode 100644 index 0000000000..1f0878770b --- /dev/null +++ b/test/cpp/thread_manager/BUILD @@ -0,0 +1,31 @@ +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) # Apache v2 + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") + +grpc_package(name = "test/cpp/thread_manager") + +grpc_cc_test( + name = "thread_manager_test", + srcs = ["thread_manager_test.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//test/cpp/util:test_config", + ], +) + diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index 8282d46694..d3d31f9dd9 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -20,10 +20,10 @@ #include #include -#include #include #include #include +#include #include "src/cpp/thread_manager/thread_manager.h" #include "test/cpp/util/test_config.h" @@ -32,13 +32,13 @@ namespace grpc { class ThreadManagerTest final : public grpc::ThreadManager { public: ThreadManagerTest() - : ThreadManager(kMinPollers, kMaxPollers), + : ThreadManager(kMinPollers, kMaxPollers, gpr_thd_new, gpr_thd_join), num_do_work_(0), num_poll_for_work_(0), num_work_found_(0) {} grpc::ThreadManager::WorkStatus PollForWork(void** tag, bool* ok) override; - void DoWork(void* tag, bool ok) override; + void DoWork(void* tag, bool ok, bool resources) override; void PerformTest(); private: @@ -89,7 +89,7 @@ grpc::ThreadManager::WorkStatus ThreadManagerTest::PollForWork(void** tag, } } -void ThreadManagerTest::DoWork(void* tag, bool ok) { +void ThreadManagerTest::DoWork(void* tag, bool ok, bool resources) { gpr_atm_no_barrier_fetch_add(&num_do_work_, 1); SleepForMs(kDoWorkDurationMsec); // Simulate doing work by sleeping } -- cgit v1.2.3 From 8fc3715a17a1b764143d0b37652a07a45d1cdf01 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 18 Dec 2017 14:33:51 -0800 Subject: Catch exceptions from sync method handlers without crashing server --- CMakeLists.txt | 41 ++++++ Makefile | 50 ++++++- build.yaml | 16 ++- include/grpc++/impl/codegen/method_handler_impl.h | 35 ++++- test/cpp/end2end/BUILD | 159 ++++++++++++--------- test/cpp/end2end/exception_test.cc | 116 +++++++++++++++ tools/run_tests/generated/sources_and_headers.json | 19 +++ tools/run_tests/generated/tests.json | 24 ++++ 8 files changed, 383 insertions(+), 77 deletions(-) create mode 100644 test/cpp/end2end/exception_test.cc (limited to 'test') diff --git a/CMakeLists.txt b/CMakeLists.txt index eed1205268..2cec087850 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -525,6 +525,7 @@ add_dependencies(buildtests_cxx cxx_string_ref_test) add_dependencies(buildtests_cxx cxx_time_test) add_dependencies(buildtests_cxx end2end_test) add_dependencies(buildtests_cxx error_details_test) +add_dependencies(buildtests_cxx exception_test) add_dependencies(buildtests_cxx filter_end2end_test) add_dependencies(buildtests_cxx generic_end2end_test) add_dependencies(buildtests_cxx golden_file_test) @@ -10188,6 +10189,46 @@ target_link_libraries(error_details_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(exception_test + test/cpp/end2end/exception_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(exception_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(exception_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(filter_end2end_test test/cpp/end2end/filter_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc diff --git a/Makefile b/Makefile index c962a12873..339c52294a 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,6 @@ CC_opt = $(DEFAULT_CC) CXX_opt = $(DEFAULT_CXX) LD_opt = $(DEFAULT_CC) LDXX_opt = $(DEFAULT_CXX) -CXXFLAGS_opt = -fno-exceptions CPPFLAGS_opt = -O2 DEFINES_opt = NDEBUG @@ -95,7 +94,6 @@ CC_dbg = $(DEFAULT_CC) CXX_dbg = $(DEFAULT_CXX) LD_dbg = $(DEFAULT_CC) LDXX_dbg = $(DEFAULT_CXX) -CXXFLAGS_dbg = -fno-exceptions CPPFLAGS_dbg = -O0 DEFINES_dbg = _DEBUG DEBUG @@ -1126,6 +1124,7 @@ cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test end2end_test: $(BINDIR)/$(CONFIG)/end2end_test error_details_test: $(BINDIR)/$(CONFIG)/error_details_test +exception_test: $(BINDIR)/$(CONFIG)/exception_test filter_end2end_test: $(BINDIR)/$(CONFIG)/filter_end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test @@ -1573,6 +1572,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ + $(BINDIR)/$(CONFIG)/exception_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ @@ -1702,6 +1702,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ + $(BINDIR)/$(CONFIG)/exception_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ @@ -2101,6 +2102,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 ) $(E) "[RUN] Testing error_details_test" $(Q) $(BINDIR)/$(CONFIG)/error_details_test || ( echo test error_details_test failed ; exit 1 ) + $(E) "[RUN] Testing exception_test" + $(Q) $(BINDIR)/$(CONFIG)/exception_test || ( echo test exception_test failed ; exit 1 ) $(E) "[RUN] Testing filter_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/filter_end2end_test || ( echo test filter_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing generic_end2end_test" @@ -14981,6 +14984,49 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/util/error_details_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc +EXCEPTION_TEST_SRC = \ + test/cpp/end2end/exception_test.cc \ + +EXCEPTION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EXCEPTION_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/exception_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/exception_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/exception_test: $(PROTOBUF_DEP) $(EXCEPTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(EXCEPTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/exception_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/exception_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_exception_test: $(EXCEPTION_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(EXCEPTION_TEST_OBJS:.o=.dep) +endif +endif + + FILTER_END2END_TEST_SRC = \ test/cpp/end2end/filter_end2end_test.cc \ diff --git a/build.yaml b/build.yaml index 42d7245981..8ab15b7741 100644 --- a/build.yaml +++ b/build.yaml @@ -4007,6 +4007,20 @@ targets: deps: - grpc++_error_details - grpc++ +- name: exception_test + gtest: true + build: test + language: c++ + src: + - test/cpp/end2end/exception_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr + uses_polling: false - name: filter_end2end_test gtest: true build: test @@ -4913,7 +4927,6 @@ configs: DEFINES: NDEBUG dbg: CPPFLAGS: -O0 - CXXFLAGS: -fno-exceptions DEFINES: _DEBUG DEBUG gcov: CC: gcc @@ -4956,7 +4969,6 @@ configs: LDFLAGS: -rdynamic opt: CPPFLAGS: -O2 - CXXFLAGS: -fno-exceptions DEFINES: NDEBUG stapprof: CPPFLAGS: -O2 -DGRPC_STAP_PROFILER diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index c0af4ca130..b72dceb1b4 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -27,6 +27,25 @@ namespace grpc { namespace internal { + +// Invoke the method handler, fill in the status, and +// return whether or not we finished safely (without an exception). +// Note that exception handling is 0-cost in most compiler/library +// implementations (except when an exception is actually thrown), +// so this process doesn't require additional overhead in the common case. +// Additionally, we don't need to return if we caught an exception or not; +// the handling is the same in either case. +template +Status CatchingFunctionHandler(F&& callable) { + try { + return callable(); + } catch (const std::exception& e) { + return Status(StatusCode::UNKNOWN, e.what()); + } catch (...) { + return Status(StatusCode::UNKNOWN, "Exception in method handler"); + } +} + /// A wrapper class of an application provided rpc method handler. template class RpcMethodHandler : public MethodHandler { @@ -43,7 +62,9 @@ class RpcMethodHandler : public MethodHandler { param.request.bbuf_ptr(), &req); ResponseType rsp; if (status.ok()) { - status = func_(service_, param.server_context, &req, &rsp); + status = CatchingFunctionHandler([this, ¶m, &req, &rsp] { + return func_(service_, param.server_context, &req, &rsp); + }); } GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); @@ -86,7 +107,9 @@ class ClientStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { ServerReader reader(param.call, param.server_context); ResponseType rsp; - Status status = func_(service_, param.server_context, &reader, &rsp); + Status status = CatchingFunctionHandler([this, ¶m, &reader, &rsp] { + return func_(service_, param.server_context, &reader, &rsp); + }); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); CallOpSet writer(param.call, param.server_context); - status = func_(service_, param.server_context, &req, &writer); + status = CatchingFunctionHandler([this, ¶m, &req, &writer] { + return func_(service_, param.server_context, &req, &writer); + }); } CallOpSet ops; @@ -172,7 +197,9 @@ class TemplatedBidiStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { Streamer stream(param.call, param.server_context); - Status status = func_(param.server_context, &stream); + Status status = CatchingFunctionHandler([this, ¶m, &stream] { + return func_(param.server_context, &stream); + }); CallOpSet ops; if (!param.server_context->sent_initial_metadata_) { diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index fa77c30aca..8894c68b95 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -16,25 +16,31 @@ licenses(["notice"]) # Apache v2 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package", "grpc_cc_binary") -grpc_package(name = "test/cpp/end2end", visibility = "public") # Allows external users to implement end2end tests. +grpc_package( + name = "test/cpp/end2end", + visibility = "public", +) # Allows external users to implement end2end tests. grpc_cc_library( name = "test_service_impl", testonly = True, srcs = ["test_service_impl.cc"], hdrs = ["test_service_impl.h"], + external_deps = [ + "gtest", + ], deps = [ "//src/proto/grpc/testing:echo_proto", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "async_end2end_test", srcs = ["async_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -47,14 +53,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "client_crash_test", srcs = ["client_crash_test.cc"], + data = [ + ":client_crash_test_server", + ], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -66,18 +75,16 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - data = [ - ":client_crash_test_server", - ], - external_deps = [ - "gtest", - ], ) grpc_cc_binary( name = "client_crash_test_server", testonly = True, srcs = ["client_crash_test_server.cc"], + external_deps = [ + "gflags", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -89,16 +96,15 @@ grpc_cc_binary( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gflags", - "gtest", - ], ) grpc_cc_library( name = "end2end_test_lib", - srcs = ["end2end_test.cc"], testonly = True, + srcs = ["end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -111,40 +117,58 @@ grpc_cc_library( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "end2end_test", deps = [ - ":end2end_test_lib" + ":end2end_test_lib", ], ) grpc_cc_test( - name = "filter_end2end_test", - srcs = ["filter_end2end_test.cc"], + name = "exception_test", + srcs = ["exception_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", "//:grpc++", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", - "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], +) + +grpc_cc_test( + name = "filter_end2end_test", + srcs = ["filter_end2end_test.cc"], external_deps = [ "gtest", ], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], ) grpc_cc_test( name = "generic_end2end_test", srcs = ["generic_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -156,14 +180,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "hybrid_end2end_test", srcs = ["hybrid_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -176,14 +200,15 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "mock_test", srcs = ["mock_test.cc"], + external_deps = [ + "gmock", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -196,15 +221,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gmock", - "gtest", - ], ) grpc_cc_test( name = "client_lb_end2end_test", srcs = ["client_lb_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -217,37 +241,38 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "grpclb_end2end_test", srcs = ["grpclb_end2end_test.cc"], + external_deps = [ + "gmock", + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", "//:grpc", "//:grpc++", + "//:grpc_resolver_fake", "//src/proto/grpc/lb/v1:load_balancer_proto", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", - "//:grpc_resolver_fake", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gmock", - "gtest", - ], ) grpc_cc_test( name = "proto_server_reflection_test", srcs = ["proto_server_reflection_test.cc"], + external_deps = [ + "gtest", + "gflags", + ], deps = [ ":test_service_impl", "//:gpr", @@ -262,15 +287,14 @@ grpc_cc_test( "//test/cpp/util:grpc++_proto_reflection_desc_db", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - "gflags", - ], ) grpc_cc_test( name = "server_builder_plugin_test", srcs = ["server_builder_plugin_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -283,14 +307,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "server_crash_test", srcs = ["server_crash_test.cc"], + data = [ + ":server_crash_test_client", + ], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -302,18 +329,16 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], - data = [ - ":server_crash_test_client", - ], ) grpc_cc_binary( name = "server_crash_test_client", testonly = True, srcs = ["server_crash_test_client.cc"], + external_deps = [ + "gflags", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -325,15 +350,14 @@ grpc_cc_binary( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gflags", - "gtest", - ], ) grpc_cc_test( name = "shutdown_test", srcs = ["shutdown_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -345,14 +369,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "streaming_throughput_test", srcs = ["streaming_throughput_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -364,14 +388,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "thread_stress_test", srcs = ["thread_stress_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -383,7 +407,4 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc new file mode 100644 index 0000000000..6545ffa530 --- /dev/null +++ b/test/cpp/end2end/exception_test.cc @@ -0,0 +1,116 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/test_config.h" + +#include + +namespace grpc { +namespace testing { + +const char* kErrorMessage = "This service caused an exception"; + +class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + Status Echo(ServerContext* server_context, const EchoRequest* request, + EchoResponse* response) override { + throw - 1; + } + Status RequestStream(ServerContext* context, + ServerReader* reader, + EchoResponse* response) override { + throw ServiceException(); + } + + private: + class ServiceException final : public std::exception { + public: + ServiceException() {} + + private: + const char* what() const noexcept override { return kErrorMessage; } + }; +}; + +class ExceptionTest : public ::testing::Test { + protected: + ExceptionTest() {} + + void SetUp() override { + ServerBuilder builder; + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { server_->Shutdown(); } + + void ResetStub() { + channel_ = server_->InProcessChannel(ChannelArguments()); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr channel_; + std::unique_ptr stub_; + std::unique_ptr server_; + ExceptingServiceImpl service_; +}; + +TEST_F(ExceptionTest, Unary) { + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("test"); + ClientContext context; + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); +} + +TEST_F(ExceptionTest, RequestStream) { + ResetStub(); + EchoResponse response; + ClientContext context; + + auto stream = stub_->RequestStream(&context, &response); + stream->WritesDone(); + Status s = stream->Finish(); + + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); + EXPECT_EQ(s.error_message(), kErrorMessage); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index d432bd0e53..137e36a432 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3160,6 +3160,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "exception_test", + "src": [ + "test/cpp/end2end/exception_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 98517cba2e..bb672bea7d 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3695,6 +3695,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "exception_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 9809ce38e9f79b4e9a0b1ec1c076cce0beee1e98 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 19 Dec 2017 09:09:52 -0800 Subject: Use appropriate preprocessor guards to allow building without exceptions --- BUILD | 18 ++++++++++++++---- bazel/grpc_build_system.bzl | 4 ++++ include/grpc++/impl/codegen/method_handler_impl.h | 10 +++++++--- include/grpc/impl/codegen/port_platform.h | 15 +++++++++++++++ test/cpp/end2end/exception_test.cc | 4 ++++ 5 files changed, 44 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/BUILD b/BUILD index dba6592f17..ebd198275e 100644 --- a/BUILD +++ b/BUILD @@ -38,6 +38,16 @@ config_setting( values = {"define": "grpc_no_ares=true"}, ) +config_setting( + name = "grpc_allow_exceptions", + values = {"define": "GRPC_ALLOW_EXCEPTIONS=1"}, +) + +config_setting( + name = "grpc_disallow_exceptions", + values = {"define": "GRPC_ALLOW_EXCEPTIONS=0"}, +) + config_setting( name = "remote_execution", values = {"define": "GRPC_PORT_ISOLATED_RUNTIME=1"}, @@ -544,24 +554,24 @@ grpc_cc_library( grpc_cc_library( name = "debug_location", - public_hdrs = ["src/core/lib/support/debug_location.h"], language = "c++", + public_hdrs = ["src/core/lib/support/debug_location.h"], ) grpc_cc_library( name = "ref_counted", - public_hdrs = ["src/core/lib/support/ref_counted.h"], language = "c++", + public_hdrs = ["src/core/lib/support/ref_counted.h"], deps = [ - "grpc_trace", "debug_location", + "grpc_trace", ], ) grpc_cc_library( name = "ref_counted_ptr", - public_hdrs = ["src/core/lib/support/ref_counted_ptr.h"], language = "c++", + public_hdrs = ["src/core/lib/support/ref_counted_ptr.h"], ) grpc_cc_library( diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index d146ca9c2c..d61eced2d9 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -60,6 +60,10 @@ def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [], defines = select({"//:grpc_no_ares": ["GRPC_ARES=0"], "//conditions:default": [],}) + select({"//:remote_execution": ["GRPC_PORT_ISOLATED_RUNTIME=1"], + "//conditions:default": [],} + + select({"//:grpc_allow_exceptions": ["GRPC_ALLOW_EXCEPTIONS=1"], + "//:grpc_disallow_exceptions": + ["GRPC_ALLOW_EXCEPTIONS=0"], "//conditions:default": [],}), hdrs = _maybe_update_cc_library_hdrs(hdrs + public_hdrs), deps = deps + _get_external_deps(external_deps), diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index b72dceb1b4..41c287231f 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -35,15 +35,19 @@ namespace internal { // so this process doesn't require additional overhead in the common case. // Additionally, we don't need to return if we caught an exception or not; // the handling is the same in either case. -template -Status CatchingFunctionHandler(F&& callable) { +template +Status CatchingFunctionHandler(Callable&& handler) { +#if GRPC_ALLOW_EXCEPTIONS try { - return callable(); + return handler(); } catch (const std::exception& e) { return Status(StatusCode::UNKNOWN, e.what()); } catch (...) { return Status(StatusCode::UNKNOWN, "Exception in method handler"); } +#else + return handler(); +#endif } /// A wrapper class of an application provided rpc method handler. diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index e6bee73ef1..becb16b5b8 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -477,6 +477,21 @@ typedef unsigned __int64 uint64_t; #endif /* GPR_ATTRIBUTE_NO_TSAN (2) */ #endif /* GPR_ATTRIBUTE_NO_TSAN (1) */ +/* GRPC_ALLOW_EXCEPTIONS should be 0 or 1 if exceptions are allowed or not */ +#ifndef GRPC_ALLOW_EXCEPTIONS +/* If not already set, set to 1 on Windows (style guide standard) but to + * 0 on non-Windows platforms unless the compiler defines __EXCEPTIONS */ +#ifdef GPR_WINDOWS +#define GRPC_ALLOW_EXCEPTIONS 1 +#else +#ifdef __EXCEPTIONS +#define GRPC_ALLOW_EXCEPTIONS 1 +#else +#define GRPC_ALLOW_EXCEPTIONS 0 +#endif +#endif +#endif + #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index 6545ffa530..7e0d5c7951 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/test_config.h" @@ -35,6 +36,7 @@ namespace testing { const char* kErrorMessage = "This service caused an exception"; +#if GRPC_ALLOW_EXCEPTIONS class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { public: Status Echo(ServerContext* server_context, const EchoRequest* request, @@ -106,6 +108,8 @@ TEST_F(ExceptionTest, RequestStream) { EXPECT_EQ(s.error_message(), kErrorMessage); } +#endif + } // namespace testing } // namespace grpc -- cgit v1.2.3 From b425fc79da44da1641b03cd6c35cf13b542c8e07 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 19 Dec 2017 10:20:12 -0800 Subject: Comment on cpp guard --- test/cpp/end2end/exception_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index 7e0d5c7951..722276d149 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -108,7 +108,7 @@ TEST_F(ExceptionTest, RequestStream) { EXPECT_EQ(s.error_message(), kErrorMessage); } -#endif +#endif // GRPC_ALLOW_EXCEPTIONS } // namespace testing } // namespace grpc -- cgit v1.2.3 From 75005775938c8844d42946f92b052fd1be79a0a9 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 9 Jan 2018 10:55:37 -0800 Subject: Address review feedback; stop using result of 'what' --- include/grpc++/impl/codegen/method_handler_impl.h | 4 +--- test/cpp/end2end/exception_test.cc | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'test') diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index ed6c146e6c..daf090f86c 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -40,10 +40,8 @@ Status CatchingFunctionHandler(Callable&& handler) { #if GRPC_ALLOW_EXCEPTIONS try { return handler(); - } catch (const std::exception& e) { - return Status(StatusCode::UNKNOWN, e.what()); } catch (...) { - return Status(StatusCode::UNKNOWN, "Exception in method handler"); + return Status(StatusCode::UNKNOWN, "Unexpected error in RPC handling"); } #else // GRPC_ALLOW_EXCEPTIONS return handler(); diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index 722276d149..76272ad08a 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -105,7 +105,6 @@ TEST_F(ExceptionTest, RequestStream) { EXPECT_FALSE(s.ok()); EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); - EXPECT_EQ(s.error_message(), kErrorMessage); } #endif // GRPC_ALLOW_EXCEPTIONS -- cgit v1.2.3 From c6406f32f626bcad9aee9582132f06bc68f4e0e5 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 10 Jan 2018 14:47:37 -0800 Subject: Implement InlinedVector independently of absl. --- CMakeLists.txt | 40 +++++++++++ Makefile | 48 +++++++++++++ build.yaml | 15 ++++ gRPC-Core.podspec | 2 + grpc.gemspec | 1 + package.xml | 1 + src/core/lib/support/vector.h | 84 +++++++++++++++++++++- test/core/support/vector_test.cc | 42 +++++++++-- tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 21 ++++++ tools/run_tests/generated/tests.json | 24 +++++++ 12 files changed, 273 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/CMakeLists.txt b/CMakeLists.txt index eed1205268..a53624978c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -594,6 +594,7 @@ add_dependencies(buildtests_cxx stress_test) add_dependencies(buildtests_cxx thread_manager_test) add_dependencies(buildtests_cxx thread_stress_test) add_dependencies(buildtests_cxx transport_pid_controller_test) +add_dependencies(buildtests_cxx vector_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx writes_per_rpc_test) endif() @@ -12495,6 +12496,45 @@ target_link_libraries(transport_pid_controller_test ${_gRPC_GFLAGS_LIBRARIES} ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(vector_test + test/core/support/vector_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(vector_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(vector_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) diff --git a/Makefile b/Makefile index 38b40804d6..a5a9f9508d 100644 --- a/Makefile +++ b/Makefile @@ -1180,6 +1180,7 @@ stress_test: $(BINDIR)/$(CONFIG)/stress_test thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test +vector_test: $(BINDIR)/$(CONFIG)/vector_test writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables @@ -1620,6 +1621,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ + $(BINDIR)/$(CONFIG)/vector_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ $(BINDIR)/$(CONFIG)/boringssl_aes_test \ $(BINDIR)/$(CONFIG)/boringssl_asn1_test \ @@ -1749,6 +1751,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ + $(BINDIR)/$(CONFIG)/vector_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \ $(BINDIR)/$(CONFIG)/resolver_component_test \ @@ -2167,6 +2170,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 ) $(E) "[RUN] Testing transport_pid_controller_test" $(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 ) + $(E) "[RUN] Testing vector_test" + $(Q) $(BINDIR)/$(CONFIG)/vector_test || ( echo test vector_test failed ; exit 1 ) $(E) "[RUN] Testing writes_per_rpc_test" $(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 ) $(E) "[RUN] Testing resolver_component_tests_runner_invoker_unsecure" @@ -17270,6 +17275,49 @@ endif endif +VECTOR_TEST_SRC = \ + test/core/support/vector_test.cc \ + +VECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(VECTOR_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/vector_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/vector_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/vector_test: $(PROTOBUF_DEP) $(VECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(VECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/vector_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/support/vector_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_vector_test: $(VECTOR_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(VECTOR_TEST_OBJS:.o=.dep) +endif +endif + + WRITES_PER_RPC_TEST_SRC = \ test/cpp/performance/writes_per_rpc_test.cc \ diff --git a/build.yaml b/build.yaml index fef7d6189f..a753253a2e 100644 --- a/build.yaml +++ b/build.yaml @@ -399,6 +399,7 @@ filegroups: - src/core/lib/support/debug_location.h - src/core/lib/support/ref_counted.h - src/core/lib/support/ref_counted_ptr.h + - src/core/lib/support/vector.h - src/core/lib/surface/alarm_internal.h - src/core/lib/surface/api_trace.h - src/core/lib/surface/call.h @@ -4798,6 +4799,20 @@ targets: - grpc - gpr_test_util - gpr +- name: vector_test + gtest: true + build: test + language: c++ + src: + - test/core/support/vector_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr + uses: + - grpc++_test - name: writes_per_rpc_test gtest: true cpu_cost: 0.5 diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index c127660dd5..a64f5e4559 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -423,6 +423,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/debug_location.h', 'src/core/lib/support/ref_counted.h', 'src/core/lib/support/ref_counted_ptr.h', + 'src/core/lib/support/vector.h', 'src/core/lib/surface/alarm_internal.h', 'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/call.h', @@ -903,6 +904,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/debug_location.h', 'src/core/lib/support/ref_counted.h', 'src/core/lib/support/ref_counted_ptr.h', + 'src/core/lib/support/vector.h', 'src/core/lib/surface/alarm_internal.h', 'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/call.h', diff --git a/grpc.gemspec b/grpc.gemspec index d185995261..95836a5029 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -349,6 +349,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/debug_location.h ) s.files += %w( src/core/lib/support/ref_counted.h ) s.files += %w( src/core/lib/support/ref_counted_ptr.h ) + s.files += %w( src/core/lib/support/vector.h ) s.files += %w( src/core/lib/surface/alarm_internal.h ) s.files += %w( src/core/lib/surface/api_trace.h ) s.files += %w( src/core/lib/surface/call.h ) diff --git a/package.xml b/package.xml index b4d8c88693..8e34b56ce7 100644 --- a/package.xml +++ b/package.xml @@ -361,6 +361,7 @@ + diff --git a/src/core/lib/support/vector.h b/src/core/lib/support/vector.h index 4a7db80676..2f249a5b9e 100644 --- a/src/core/lib/support/vector.h +++ b/src/core/lib/support/vector.h @@ -19,13 +19,93 @@ #ifndef GRPC_CORE_LIB_SUPPORT_VECTOR_H #define GRPC_CORE_LIB_SUPPORT_VECTOR_H -#include "absl/container/inlined_vector.h" +#include + #include "src/core/lib/support/memory.h" namespace grpc_core { +// NOTE: We eventually want to use absl::InlinedVector here. However, +// there are currently build problems that prevent us from using absl. +// In the interim, we define a custom implementation as a place-holder, +// with the intent to eventually replace this with the absl +// implementation. +// +// This place-holder implementation does not implement the full set of +// functionality from the absl version; it has just the methods that we +// currently happen to need in gRPC. If additional functionality is +// needed before this gets replaced with the absl version, it can be +// added, with the following proviso: +// +// ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl +// IMPLEMENTATION! +// +// TODO(ctiller, nnoble, roth): Replace this with absl::InlinedVector +// once we integrate absl into the gRPC build system in a usable way. template -using InlinedVector = absl::InlinedVector>; +class InlinedVector { + public: + InlinedVector() {} + ~InlinedVector() { + for (size_t i = 0; i < size_ && i < N; ++i) { + T& value = *reinterpret_cast(inline_ + i); + value.~T(); + } + if (size_ > N) { // Avoid subtracting two signed values. + for (size_t i = 0; i < size_ - N; ++i) { + dynamic_[i].~T(); + } + } + gpr_free(dynamic_); + } + + // For now, we do not support copying. + InlinedVector(const InlinedVector&) = delete; + InlinedVector& operator=(const InlinedVector&) = delete; + + T& operator[](size_t offset) { + assert(offset < size_); + if (offset < N) { + return *reinterpret_cast(inline_ + offset); + } else { + return dynamic_[offset - N]; + } + } + + template + void emplace_back(Args&&... args) { + if (size_ < N) { + new (&inline_[size_]) T(std::forward(args)...); + } else { + if (size_ - N == dynamic_capacity_) { + size_t new_capacity = + dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2; + T* new_dynamic = static_cast(gpr_malloc(sizeof(T) * new_capacity)); + for (size_t i = 0; i < dynamic_capacity_; ++i) { + new (&new_dynamic[i]) T(std::move(dynamic_[i])); + dynamic_[i].~T(); + } + gpr_free(dynamic_); + dynamic_ = new_dynamic; + dynamic_capacity_ = new_capacity; + } + new (&dynamic_[size_ - N]) T(std::forward(args)...); + } + ++size_; + } + + void push_back(const T& value) { emplace_back(value); } + + void push_back(T&& value) { emplace_back(std::move(value)); } + + size_t size() const { return size_; } + + private: + typename std::aligned_storage::type inline_[N]; + T* dynamic_ = nullptr; + size_t size_ = 0; + size_t dynamic_capacity_ = 0; +}; } // namespace grpc_core diff --git a/test/core/support/vector_test.cc b/test/core/support/vector_test.cc index aad9f3be90..82607a1b26 100644 --- a/test/core/support/vector_test.cc +++ b/test/core/support/vector_test.cc @@ -18,18 +18,50 @@ #include "src/core/lib/support/vector.h" #include +#include "src/core/lib/support/memory.h" #include "test/core/util/test_config.h" namespace grpc_core { namespace testing { TEST(InlinedVectorTest, CreateAndIterate) { - InlinedVector v{1, 2, 3}; - int sum = 0; - for (auto i : v) { - sum += i; + const int kNumElements = 9; + InlinedVector v; + for (int i = 0; i < kNumElements; ++i) { + v.push_back(i); } - EXPECT_EQ(6, sum); + EXPECT_EQ(static_cast(kNumElements), v.size()); + for (int i = 0; i < kNumElements; ++i) { + EXPECT_EQ(i, v[i]); + } +} + +TEST(InlinedVectorTest, ValuesAreInlined) { + const int kNumElements = 5; + InlinedVector v; + for (int i = 0; i < kNumElements; ++i) { + v.push_back(i); + } + EXPECT_EQ(static_cast(kNumElements), v.size()); + for (int i = 0; i < kNumElements; ++i) { + EXPECT_EQ(i, v[i]); + } +} + +TEST(InlinedVectorTest, PushBackWithMove) { + InlinedVector, 1> v; + UniquePtr i = MakeUnique(3); + v.push_back(std::move(i)); + EXPECT_EQ(nullptr, i.get()); + EXPECT_EQ(1UL, v.size()); + EXPECT_EQ(3, *v[0]); +} + +TEST(InlinedVectorTest, EmplaceBack) { + InlinedVector, 1> v; + v.emplace_back(New(3)); + EXPECT_EQ(1UL, v.size()); + EXPECT_EQ(3, *v[0]); } } // namespace testing diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index d09b325c97..211149ac26 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1047,6 +1047,7 @@ src/core/lib/support/string_windows.h \ src/core/lib/support/thd_internal.h \ src/core/lib/support/time_precise.h \ src/core/lib/support/tmpfile.h \ +src/core/lib/support/vector.h \ src/core/lib/surface/alarm_internal.h \ src/core/lib/surface/api_trace.h \ src/core/lib/surface/call.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1aff0075a6..5bd707d545 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1333,6 +1333,7 @@ src/core/lib/support/tmpfile.h \ src/core/lib/support/tmpfile_msys.cc \ src/core/lib/support/tmpfile_posix.cc \ src/core/lib/support/tmpfile_windows.cc \ +src/core/lib/support/vector.h \ src/core/lib/support/wrap_memcpy.cc \ src/core/lib/surface/README.md \ src/core/lib/surface/alarm.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index d432bd0e53..80bd0d6185 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -4262,6 +4262,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "vector_test", + "src": [ + "test/core/support/vector_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -8250,6 +8269,7 @@ "src/core/lib/support/debug_location.h", "src/core/lib/support/ref_counted.h", "src/core/lib/support/ref_counted_ptr.h", + "src/core/lib/support/vector.h", "src/core/lib/surface/alarm_internal.h", "src/core/lib/surface/api_trace.h", "src/core/lib/surface/call.h", @@ -8389,6 +8409,7 @@ "src/core/lib/support/debug_location.h", "src/core/lib/support/ref_counted.h", "src/core/lib/support/ref_counted_ptr.h", + "src/core/lib/support/vector.h", "src/core/lib/surface/alarm_internal.h", "src/core/lib/surface/api_trace.h", "src/core/lib/surface/call.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 98517cba2e..6b83cecd41 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -4504,6 +4504,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "vector_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 9ee9c924d8f23604a8ab78089b1706b5b00e971a Mon Sep 17 00:00:00 2001 From: Dan Zhang Date: Wed, 10 Jan 2018 18:04:25 -0500 Subject: change to pass in value --- src/core/lib/iomgr/udp_server.cc | 38 +++++++++++++++++++++++++------------- src/core/lib/iomgr/udp_server.h | 1 + test/core/iomgr/udp_server_test.cc | 23 +++++++++++++++-------- 3 files changed, 41 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc index 6dde7b9611..8deb0ea544 100644 --- a/src/core/lib/iomgr/udp_server.cc +++ b/src/core/lib/iomgr/udp_server.cc @@ -280,11 +280,10 @@ static int bind_socket(grpc_socket_factory* socket_factory, int sockfd, /* Prepare a recently-created socket for listening. */ static int prepare_socket(grpc_socket_factory* socket_factory, int fd, - const grpc_resolved_address* addr) { + const grpc_resolved_address* addr, + size_t rcv_buf_size, size_t snd_buf_size) { grpc_resolved_address sockname_temp; struct sockaddr* addr_ptr = (struct sockaddr*)addr->addr; - /* Set send/receive socket buffers to 10 MB */ - int buffer_size_bytes = 1024 * 1024 * 10; if (fd < 0) { goto error; @@ -325,18 +324,25 @@ static int prepare_socket(grpc_socket_factory* socket_factory, int fd, goto error; } - if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes", - buffer_size_bytes); + if (grpc_set_socket_sndbuf(fd, snd_buf_size) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Failed to set send buffer size to %lu bytes", + snd_buf_size); goto error; } - if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes", - buffer_size_bytes); + if (grpc_set_socket_rcvbuf(fd, rcv_buf_size) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Failed to set receive buffer size to %lu bytes", + rcv_buf_size); goto error; } + { + int get_overflow = 1; + if (0 != setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, + sizeof(get_overflow))) { + gpr_log(GPR_INFO, "Failed to set socket overflow support"); + } + } return grpc_sockaddr_get_port(&sockname_temp); error: @@ -451,6 +457,8 @@ static void on_write(void* arg, grpc_error* error) { static int add_socket_to_server(grpc_udp_server* s, int fd, const grpc_resolved_address* addr, + size_t rcv_buf_size, + size_t snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, @@ -460,7 +468,8 @@ static int add_socket_to_server(grpc_udp_server* s, int fd, char* addr_str; char* name; - port = prepare_socket(s->socket_factory, fd, addr); + port = + prepare_socket(s->socket_factory, fd, addr, rcv_buf_size, snd_buf_size); if (port >= 0) { grpc_sockaddr_to_string(&addr_str, addr, 1); gpr_asprintf(&name, "udp-server-listener:%s", addr_str); @@ -495,6 +504,7 @@ static int add_socket_to_server(grpc_udp_server* s, int fd, int grpc_udp_server_add_port(grpc_udp_server* s, const grpc_resolved_address* addr, + size_t rcv_buf_size, size_t snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, @@ -545,8 +555,9 @@ int grpc_udp_server_add_port(grpc_udp_server* s, // TODO(rjshade): Test and propagate the returned grpc_error*: GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory( s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd)); - allocated_port1 = add_socket_to_server(s, fd, addr, start_cb, read_cb, - write_cb, orphan_cb); + allocated_port1 = + add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size, start_cb, + read_cb, write_cb, orphan_cb); if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { goto done; } @@ -569,7 +580,8 @@ int grpc_udp_server_add_port(grpc_udp_server* s, addr = &addr4_copy; } allocated_port2 = - add_socket_to_server(s, fd, addr, start_cb, read_cb, write_cb, orphan_cb); + add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size, start_cb, + read_cb, write_cb, orphan_cb); done: gpr_free(allocated_addr); diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h index a469ab9be5..ec18716f39 100644 --- a/src/core/lib/iomgr/udp_server.h +++ b/src/core/lib/iomgr/udp_server.h @@ -68,6 +68,7 @@ int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index); all of the multiple socket port matching logic in one place */ int grpc_udp_server_add_port(grpc_udp_server* s, const grpc_resolved_address* addr, + size_t rcv_buf_size, size_t snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc index dc1248bc1c..5245840ba9 100644 --- a/test/core/iomgr/udp_server_test.cc +++ b/test/core/iomgr/udp_server_test.cc @@ -51,6 +51,9 @@ static int g_number_of_bytes_read = 0; static int g_number_of_orphan_calls = 0; static int g_number_of_starts = 0; +size_t rcv_buf_size = 1024; +size_t snd_buf_size = 1024; + static void on_start(grpc_fd* emfd, void* user_data) { g_number_of_starts++; } static bool on_read(grpc_fd* emfd) { @@ -177,8 +180,9 @@ static void test_no_op_with_port(void) { memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_start, on_read, - on_write, on_fd_orphaned)); + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size, + snd_buf_size, on_start, on_read, on_write, + on_fd_orphaned)); grpc_udp_server_destroy(s, nullptr); @@ -207,8 +211,9 @@ static void test_no_op_with_port_and_socket_factory(void) { memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_start, on_read, - on_write, on_fd_orphaned)); + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size, + snd_buf_size, on_start, on_read, on_write, + on_fd_orphaned)); GPR_ASSERT(socket_factory->number_of_socket_calls == 1); GPR_ASSERT(socket_factory->number_of_bind_calls == 1); @@ -233,8 +238,9 @@ static void test_no_op_with_port_and_start(void) { memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_start, on_read, - on_write, on_fd_orphaned)); + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size, + snd_buf_size, on_start, on_read, on_write, + on_fd_orphaned)); grpc_udp_server_start(s, nullptr, 0, nullptr); GPR_ASSERT(g_number_of_starts == 1); @@ -265,8 +271,9 @@ static void test_receive(int number_of_clients) { memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_storage); addr->ss_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_start, on_read, - on_write, on_fd_orphaned)); + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size, + snd_buf_size, on_start, on_read, on_write, + on_fd_orphaned)); svrfd = grpc_udp_server_get_fd(s, 0); GPR_ASSERT(svrfd >= 0); -- cgit v1.2.3 From 1d91362f8124751ecfc1929df207006cabb41dae Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Wed, 10 Jan 2018 15:59:05 -0800 Subject: exec_ctx_fwd.h should never have been in public headers --- BUILD | 1 - CMakeLists.txt | 10 --------- Makefile | 10 --------- build.yaml | 1 - gRPC-Core.podspec | 1 - grpc.gemspec | 1 - include/grpc/impl/codegen/exec_ctx_fwd.h | 26 ---------------------- include/grpc/impl/codegen/grpc_types.h | 1 - include/grpc/impl/codegen/slice.h | 1 - include/grpc/module.modulemap | 1 - package.xml | 1 - src/core/lib/iomgr/closure.h | 1 - src/core/lib/iomgr/iomgr.h | 1 - test/core/surface/public_headers_must_be_c89.c | 1 - tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core | 1 - tools/doxygen/Doxyfile.core.internal | 1 - tools/run_tests/generated/sources_and_headers.json | 2 -- 19 files changed, 63 deletions(-) delete mode 100644 include/grpc/impl/codegen/exec_ctx_fwd.h (limited to 'test') diff --git a/BUILD b/BUILD index dba6592f17..804c6cee02 100644 --- a/BUILD +++ b/BUILD @@ -1006,7 +1006,6 @@ grpc_cc_library( "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/exec_ctx_fwd.h", "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index eed1205268..fa020e009d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1080,7 +1080,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -1394,7 +1393,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -1680,7 +1678,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -1950,7 +1947,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -2239,7 +2235,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -2552,7 +2547,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -3038,7 +3032,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -3438,7 +3431,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -3579,7 +3571,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h @@ -3784,7 +3775,6 @@ foreach(_hdr include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h diff --git a/Makefile b/Makefile index 38b40804d6..10c6530313 100644 --- a/Makefile +++ b/Makefile @@ -3226,7 +3226,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -3540,7 +3539,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -3827,7 +3825,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -4088,7 +4085,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -4354,7 +4350,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -4646,7 +4641,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -5133,7 +5127,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -5526,7 +5519,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -5644,7 +5636,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ @@ -5854,7 +5845,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ - include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ diff --git a/build.yaml b/build.yaml index fef7d6189f..9aff5585e0 100644 --- a/build.yaml +++ b/build.yaml @@ -485,7 +485,6 @@ filegroups: - include/grpc/impl/codegen/byte_buffer_reader.h - include/grpc/impl/codegen/compression_types.h - include/grpc/impl/codegen/connectivity_state.h - - include/grpc/impl/codegen/exec_ctx_fwd.h - include/grpc/impl/codegen/grpc_types.h - include/grpc/impl/codegen/propagation_bits.h - include/grpc/impl/codegen/slice.h diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index c127660dd5..c007348c81 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -152,7 +152,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/byte_buffer_reader.h', 'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/connectivity_state.h', - 'include/grpc/impl/codegen/exec_ctx_fwd.h', 'include/grpc/impl/codegen/grpc_types.h', 'include/grpc/impl/codegen/propagation_bits.h', 'include/grpc/impl/codegen/slice.h', diff --git a/grpc.gemspec b/grpc.gemspec index d185995261..c7302785c7 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -149,7 +149,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) - s.files += %w( include/grpc/impl/codegen/exec_ctx_fwd.h ) s.files += %w( include/grpc/impl/codegen/grpc_types.h ) s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) diff --git a/include/grpc/impl/codegen/exec_ctx_fwd.h b/include/grpc/impl/codegen/exec_ctx_fwd.h deleted file mode 100644 index 005ff14e7e..0000000000 --- a/include/grpc/impl/codegen/exec_ctx_fwd.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H -#define GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H - -/* forward declaration for exec_ctx.h */ -struct grpc_exec_ctx; -typedef struct grpc_exec_ctx grpc_exec_ctx; - -#endif /* GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H */ diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index fcbc8ac5a1..d481a70ab9 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index ad026b685e..a3cd1f1bbe 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -23,7 +23,6 @@ #include -#include #include typedef struct grpc_slice grpc_slice; diff --git a/include/grpc/module.modulemap b/include/grpc/module.modulemap index 67136cba8a..da95515d8e 100644 --- a/include/grpc/module.modulemap +++ b/include/grpc/module.modulemap @@ -30,7 +30,6 @@ framework module grpc { header "impl/codegen/byte_buffer_reader.h" header "impl/codegen/compression_types.h" header "impl/codegen/connectivity_state.h" - header "impl/codegen/exec_ctx_fwd.h" header "impl/codegen/grpc_types.h" header "impl/codegen/propagation_bits.h" header "impl/codegen/slice.h" diff --git a/package.xml b/package.xml index b4d8c88693..adc98330de 100644 --- a/package.xml +++ b/package.xml @@ -161,7 +161,6 @@ - diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index 88af76006a..4c58c0e4bf 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index 3f238c660a..c7cde7ea59 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -19,7 +19,6 @@ #ifndef GRPC_CORE_LIB_IOMGR_IOMGR_H #define GRPC_CORE_LIB_IOMGR_IOMGR_H -#include #include "src/core/lib/iomgr/port.h" /** Initializes the iomgr. */ diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 8d2384ba61..7fd36a241a 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index e62278cb9f..5bdbcd71f5 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -887,7 +887,6 @@ include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index d09b325c97..b57674ba8e 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -888,7 +888,6 @@ include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 6ce9041747..916d3b1e49 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -818,7 +818,6 @@ include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/gpr_slice.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1aff0075a6..e41123abf6 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -818,7 +818,6 @@ include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/fork.h \ include/grpc/impl/codegen/gpr_slice.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index d432bd0e53..f7898a90a9 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -8505,7 +8505,6 @@ "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/exec_ctx_fwd.h", "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/slice.h", @@ -8519,7 +8518,6 @@ "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/exec_ctx_fwd.h", "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/slice.h", -- cgit v1.2.3 From 324703db51b43e150d9d8ffbcceb9d2096e26a9f Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 11 Jan 2018 07:41:31 -0800 Subject: Fix existing ref counting classes and add new ones. --- BUILD | 10 ++ CMakeLists.txt | 40 +++++ Makefile | 48 ++++++ build.yaml | 15 ++ gRPC-Core.podspec | 2 + grpc.gemspec | 1 + package.xml | 1 + src/core/lib/support/abstract.h | 5 + src/core/lib/support/orphanable.h | 166 +++++++++++++++++++++ src/core/lib/support/ref_counted.h | 13 +- test/core/support/BUILD | 13 ++ test/core/support/orphanable_test.cc | 114 ++++++++++++++ test/core/support/ref_counted_test.cc | 4 +- tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 21 +++ tools/run_tests/generated/tests.json | 24 +++ 17 files changed, 477 insertions(+), 2 deletions(-) create mode 100644 src/core/lib/support/orphanable.h create mode 100644 test/core/support/orphanable_test.cc (limited to 'test') diff --git a/BUILD b/BUILD index 804c6cee02..f478652df2 100644 --- a/BUILD +++ b/BUILD @@ -548,6 +548,16 @@ grpc_cc_library( language = "c++", ) +grpc_cc_library( + name = "orphanable", + public_hdrs = ["src/core/lib/support/orphanable.h"], + language = "c++", + deps = [ + "grpc_trace", + "debug_location", + ], +) + grpc_cc_library( name = "ref_counted", public_hdrs = ["src/core/lib/support/ref_counted.h"], diff --git a/CMakeLists.txt b/CMakeLists.txt index 78ccfb2132..863c192a87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -558,6 +558,7 @@ add_dependencies(buildtests_cxx memory_test) add_dependencies(buildtests_cxx metrics_client) add_dependencies(buildtests_cxx mock_test) add_dependencies(buildtests_cxx noop-benchmark) +add_dependencies(buildtests_cxx orphanable_test) add_dependencies(buildtests_cxx proto_server_reflection_test) add_dependencies(buildtests_cxx proto_utils_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -11328,6 +11329,45 @@ target_link_libraries(noop-benchmark endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(orphanable_test + test/core/support/orphanable_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(orphanable_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(orphanable_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(proto_server_reflection_test test/cpp/end2end/proto_server_reflection_test.cc third_party/googletest/googletest/src/gtest-all.cc diff --git a/Makefile b/Makefile index f50163efdc..9e60130f67 100644 --- a/Makefile +++ b/Makefile @@ -1154,6 +1154,7 @@ memory_test: $(BINDIR)/$(CONFIG)/memory_test metrics_client: $(BINDIR)/$(CONFIG)/metrics_client mock_test: $(BINDIR)/$(CONFIG)/mock_test noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark +orphanable_test: $(BINDIR)/$(CONFIG)/orphanable_test proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test proto_utils_test: $(BINDIR)/$(CONFIG)/proto_utils_test qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test @@ -1595,6 +1596,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/metrics_client \ $(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/noop-benchmark \ + $(BINDIR)/$(CONFIG)/orphanable_test \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_utils_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \ @@ -1725,6 +1727,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/metrics_client \ $(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/noop-benchmark \ + $(BINDIR)/$(CONFIG)/orphanable_test \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_utils_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \ @@ -2132,6 +2135,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/mock_test || ( echo test mock_test failed ; exit 1 ) $(E) "[RUN] Testing noop-benchmark" $(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 ) + $(E) "[RUN] Testing orphanable_test" + $(Q) $(BINDIR)/$(CONFIG)/orphanable_test || ( echo test orphanable_test failed ; exit 1 ) $(E) "[RUN] Testing proto_server_reflection_test" $(Q) $(BINDIR)/$(CONFIG)/proto_server_reflection_test || ( echo test proto_server_reflection_test failed ; exit 1 ) $(E) "[RUN] Testing proto_utils_test" @@ -16088,6 +16093,49 @@ endif endif +ORPHANABLE_TEST_SRC = \ + test/core/support/orphanable_test.cc \ + +ORPHANABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ORPHANABLE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/orphanable_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/orphanable_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/orphanable_test: $(PROTOBUF_DEP) $(ORPHANABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(ORPHANABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/orphanable_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/support/orphanable_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_orphanable_test: $(ORPHANABLE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(ORPHANABLE_TEST_OBJS:.o=.dep) +endif +endif + + PROTO_SERVER_REFLECTION_TEST_SRC = \ test/cpp/end2end/proto_server_reflection_test.cc \ diff --git a/build.yaml b/build.yaml index db2ff8828b..8a34ade959 100644 --- a/build.yaml +++ b/build.yaml @@ -397,6 +397,7 @@ filegroups: - src/core/lib/slice/slice_internal.h - src/core/lib/slice/slice_string_helpers.h - src/core/lib/support/debug_location.h + - src/core/lib/support/orphanable.h - src/core/lib/support/ref_counted.h - src/core/lib/support/ref_counted_ptr.h - src/core/lib/support/vector.h @@ -4390,6 +4391,20 @@ targets: deps: - benchmark defaults: benchmark +- name: orphanable_test + gtest: true + build: test + language: c++ + src: + - test/core/support/orphanable_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr + uses: + - grpc++_test - name: proto_server_reflection_test gtest: true build: test diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 358fad3d98..d064ac80ae 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -420,6 +420,7 @@ Pod::Spec.new do |s| 'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/support/debug_location.h', + 'src/core/lib/support/orphanable.h', 'src/core/lib/support/ref_counted.h', 'src/core/lib/support/ref_counted_ptr.h', 'src/core/lib/support/vector.h', @@ -901,6 +902,7 @@ Pod::Spec.new do |s| 'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/support/debug_location.h', + 'src/core/lib/support/orphanable.h', 'src/core/lib/support/ref_counted.h', 'src/core/lib/support/ref_counted_ptr.h', 'src/core/lib/support/vector.h', diff --git a/grpc.gemspec b/grpc.gemspec index 7547bc85de..f8afaa5803 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -346,6 +346,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/slice/slice_internal.h ) s.files += %w( src/core/lib/slice/slice_string_helpers.h ) s.files += %w( src/core/lib/support/debug_location.h ) + s.files += %w( src/core/lib/support/orphanable.h ) s.files += %w( src/core/lib/support/ref_counted.h ) s.files += %w( src/core/lib/support/ref_counted_ptr.h ) s.files += %w( src/core/lib/support/vector.h ) diff --git a/package.xml b/package.xml index ff3d0797ab..8c590348b6 100644 --- a/package.xml +++ b/package.xml @@ -358,6 +358,7 @@ + diff --git a/src/core/lib/support/abstract.h b/src/core/lib/support/abstract.h index 5498769a7d..1dffa30128 100644 --- a/src/core/lib/support/abstract.h +++ b/src/core/lib/support/abstract.h @@ -26,4 +26,9 @@ #define GRPC_ABSTRACT_BASE_CLASS \ static void operator delete(void* p) { abort(); } +// gRPC currently can't depend on libstdc++, so we can't use "= 0" for +// pure virtual methods. Instead, we use this macro. +#define GRPC_ABSTRACT \ + { GPR_ASSERT(false); } + #endif /* GRPC_CORE_LIB_SUPPORT_ABSTRACT_H */ diff --git a/src/core/lib/support/orphanable.h b/src/core/lib/support/orphanable.h new file mode 100644 index 0000000000..63eda2e08b --- /dev/null +++ b/src/core/lib/support/orphanable.h @@ -0,0 +1,166 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SUPPORT_ORPHANABLE_H +#define GRPC_CORE_LIB_SUPPORT_ORPHANABLE_H + +#include +#include + +#include + +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/support/abstract.h" +#include "src/core/lib/support/debug_location.h" +#include "src/core/lib/support/memory.h" + +namespace grpc_core { + +// A base class for orphanable objects. +class Orphanable { + public: + // Gives up ownership of the object. The implementation must arrange + // to destroy the object without further interaction from the caller. + virtual void Orphan() GRPC_ABSTRACT; + + // Not copyable or movable. + Orphanable(const Orphanable&) = delete; + Orphanable& operator=(const Orphanable&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + Orphanable() {} + virtual ~Orphanable() {} +}; + +template +class OrphanableDelete { + public: + void operator()(T* p) { p->Orphan(); } +}; + +template > +using OrphanablePtr = std::unique_ptr; + +template +inline OrphanablePtr MakeOrphanable(Args&&... args) { + return OrphanablePtr(New(std::forward(args)...)); +} + +// A type of Orphanable with internal ref-counting. +class InternallyRefCounted : public Orphanable { + public: + // Not copyable nor movable. + InternallyRefCounted(const InternallyRefCounted&) = delete; + InternallyRefCounted& operator=(const InternallyRefCounted&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + InternallyRefCounted() { gpr_ref_init(&refs_, 1); } + virtual ~InternallyRefCounted() {} + + void Ref() { gpr_ref(&refs_); } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + private: + gpr_refcount refs_; +}; + +// An alternative version of the InternallyRefCounted base class that +// supports tracing. This is intended to be used in cases where the +// object will be handled both by idiomatic C++ code using smart +// pointers and legacy code that is manually calling Ref() and Unref(). +// Once all of our code is converted to idiomatic C++, we may be able to +// eliminate this class. +class InternallyRefCountedWithTracing : public Orphanable { + public: + // Not copyable nor movable. + InternallyRefCountedWithTracing(const InternallyRefCountedWithTracing&) = + delete; + InternallyRefCountedWithTracing& operator=( + const InternallyRefCountedWithTracing&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + InternallyRefCountedWithTracing() + : InternallyRefCountedWithTracing(static_cast(nullptr)) {} + + explicit InternallyRefCountedWithTracing(TraceFlag* trace_flag) + : trace_flag_(trace_flag) { + gpr_ref_init(&refs_, 1); + } + +#ifdef NDEBUG + explicit InternallyRefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) + : InternallyRefCountedWithTracing() {} +#endif + + virtual ~InternallyRefCountedWithTracing() {} + + void Ref() { gpr_ref(&refs_); } + + void Ref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs + 1, reason); + } + Ref(); + } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + void Unref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs - 1, reason); + } + Unref(); + } + + private: + TraceFlag* trace_flag_ = nullptr; + gpr_refcount refs_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SUPPORT_ORPHANABLE_H */ diff --git a/src/core/lib/support/ref_counted.h b/src/core/lib/support/ref_counted.h index 4c662f9119..48c11f7bbf 100644 --- a/src/core/lib/support/ref_counted.h +++ b/src/core/lib/support/ref_counted.h @@ -23,6 +23,7 @@ #include #include "src/core/lib/debug/trace.h" +#include "src/core/lib/support/abstract.h" #include "src/core/lib/support/debug_location.h" #include "src/core/lib/support/memory.h" @@ -45,6 +46,8 @@ class RefCounted { RefCounted(const RefCounted&) = delete; RefCounted& operator=(const RefCounted&) = delete; + GRPC_ABSTRACT_BASE_CLASS + protected: // Allow Delete() to access destructor. template @@ -98,18 +101,26 @@ class RefCountedWithTracing { RefCountedWithTracing(const RefCountedWithTracing&) = delete; RefCountedWithTracing& operator=(const RefCountedWithTracing&) = delete; + GRPC_ABSTRACT_BASE_CLASS + protected: // Allow Delete() to access destructor. template friend void Delete(T*); - RefCountedWithTracing() : RefCountedWithTracing(nullptr) {} + RefCountedWithTracing() + : RefCountedWithTracing(static_cast(nullptr)) {} explicit RefCountedWithTracing(TraceFlag* trace_flag) : trace_flag_(trace_flag) { gpr_ref_init(&refs_, 1); } +#ifdef NDEBUG + explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) + : RefCountedWithTracing() {} +#endif + virtual ~RefCountedWithTracing() {} private: diff --git a/test/core/support/BUILD b/test/core/support/BUILD index 4372b49b54..c8fa046da1 100644 --- a/test/core/support/BUILD +++ b/test/core/support/BUILD @@ -214,6 +214,19 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "orphanable_test", + srcs = ["orphanable_test.cc"], + language = "C++", + deps = [ + "//:orphanable", + "//test/core/util:gpr_test_util", + ], + external_deps = [ + "gtest", + ], +) + grpc_cc_test( name = "ref_counted_test", srcs = ["ref_counted_test.cc"], diff --git a/test/core/support/orphanable_test.cc b/test/core/support/orphanable_test.cc new file mode 100644 index 0000000000..e07017ab1e --- /dev/null +++ b/test/core/support/orphanable_test.cc @@ -0,0 +1,114 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/orphanable.h" + +#include + +#include "src/core/lib/support/memory.h" +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { +namespace { + +class Foo : public Orphanable { + public: + Foo() : Foo(0) {} + explicit Foo(int value) : value_(value) {} + void Orphan() override { Delete(this); } + int value() const { return value_; } + + private: + int value_; +}; + +TEST(Orphanable, Basic) { + Foo* foo = New(); + foo->Orphan(); +} + +TEST(OrphanablePtr, Basic) { + OrphanablePtr foo(New()); + EXPECT_EQ(0, foo->value()); +} + +TEST(MakeOrphanable, DefaultConstructor) { + auto foo = MakeOrphanable(); + EXPECT_EQ(0, foo->value()); +} + +TEST(MakeOrphanable, WithParameters) { + auto foo = MakeOrphanable(5); + EXPECT_EQ(5, foo->value()); +} + +class Bar : public InternallyRefCounted { + public: + Bar() : Bar(0) {} + explicit Bar(int value) : value_(value) {} + void Orphan() override { Unref(); } + int value() const { return value_; } + + void StartWork() { Ref(); } + void FinishWork() { Unref(); } + + private: + int value_; +}; + +TEST(OrphanablePtr, InternallyRefCounted) { + auto bar = MakeOrphanable(); + bar->StartWork(); + bar->FinishWork(); +} + +// Note: We use DebugOnlyTraceFlag instead of TraceFlag to ensure that +// things build properly in both debug and non-debug cases. +DebugOnlyTraceFlag baz_tracer(true, "baz"); + +class Baz : public InternallyRefCountedWithTracing { + public: + Baz() : Baz(0) {} + explicit Baz(int value) + : InternallyRefCountedWithTracing(&baz_tracer), value_(value) {} + void Orphan() override { Unref(); } + int value() const { return value_; } + + void StartWork() { Ref(DEBUG_LOCATION, "work"); } + void FinishWork() { Unref(DEBUG_LOCATION, "work"); } + + private: + int value_; +}; + +TEST(OrphanablePtr, InternallyRefCountedWithTracing) { + auto baz = MakeOrphanable(); + baz->StartWork(); + baz->FinishWork(); +} + +} // namespace +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/support/ref_counted_test.cc b/test/core/support/ref_counted_test.cc index be9b6ff7c2..0629e3ff5f 100644 --- a/test/core/support/ref_counted_test.cc +++ b/test/core/support/ref_counted_test.cc @@ -44,7 +44,9 @@ TEST(RefCounted, ExtraRef) { foo->Unref(); } -TraceFlag foo_tracer(true, "foo"); +// Note: We use DebugOnlyTraceFlag instead of TraceFlag to ensure that +// things build properly in both debug and non-debug cases. +DebugOnlyTraceFlag foo_tracer(true, "foo"); class FooWithTracing : public RefCountedWithTracing { public: diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index d9184f49a2..85bbeed088 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1038,6 +1038,7 @@ src/core/lib/support/manual_constructor.h \ src/core/lib/support/memory.h \ src/core/lib/support/mpscq.h \ src/core/lib/support/murmur_hash.h \ +src/core/lib/support/orphanable.h \ src/core/lib/support/ref_counted.h \ src/core/lib/support/ref_counted_ptr.h \ src/core/lib/support/spinlock.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 3d3c6711d0..4bf0fc74d1 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1304,6 +1304,7 @@ src/core/lib/support/mpscq.cc \ src/core/lib/support/mpscq.h \ src/core/lib/support/murmur_hash.cc \ src/core/lib/support/murmur_hash.h \ +src/core/lib/support/orphanable.h \ src/core/lib/support/ref_counted.h \ src/core/lib/support/ref_counted_ptr.h \ src/core/lib/support/spinlock.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 51f0ac7ca6..a20acb1fef 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3688,6 +3688,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "orphanable_test", + "src": [ + "test/core/support/orphanable_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -8267,6 +8286,7 @@ "src/core/lib/slice/slice_internal.h", "src/core/lib/slice/slice_string_helpers.h", "src/core/lib/support/debug_location.h", + "src/core/lib/support/orphanable.h", "src/core/lib/support/ref_counted.h", "src/core/lib/support/ref_counted_ptr.h", "src/core/lib/support/vector.h", @@ -8407,6 +8427,7 @@ "src/core/lib/slice/slice_internal.h", "src/core/lib/slice/slice_string_helpers.h", "src/core/lib/support/debug_location.h", + "src/core/lib/support/orphanable.h", "src/core/lib/support/ref_counted.h", "src/core/lib/support/ref_counted_ptr.h", "src/core/lib/support/vector.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 6b83cecd41..57b934d9c6 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -4053,6 +4053,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "orphanable_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 3742b724c9deac411b51dfc7b1ac6818f61550e3 Mon Sep 17 00:00:00 2001 From: Dan Zhang Date: Thu, 11 Jan 2018 13:02:38 -0500 Subject: change to int type --- src/core/lib/iomgr/udp_server.cc | 6 +++--- src/core/lib/iomgr/udp_server.h | 2 +- test/core/iomgr/udp_server_test.cc | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc index 2df10ee09a..a9a3f3aba5 100644 --- a/src/core/lib/iomgr/udp_server.cc +++ b/src/core/lib/iomgr/udp_server.cc @@ -285,7 +285,7 @@ static int bind_socket(grpc_socket_factory* socket_factory, int sockfd, /* Prepare a recently-created socket for listening. */ static int prepare_socket(grpc_socket_factory* socket_factory, int fd, const grpc_resolved_address* addr, - size_t rcv_buf_size, size_t snd_buf_size) { + int rcv_buf_size, int snd_buf_size) { grpc_resolved_address sockname_temp; struct sockaddr* addr_ptr = (struct sockaddr*)addr->addr; @@ -461,7 +461,7 @@ static void on_write(void* arg, grpc_error* error) { static int add_socket_to_server(grpc_udp_server* s, int fd, const grpc_resolved_address* addr, - size_t rcv_buf_size, size_t snd_buf_size, + int rcv_buf_size, int snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, @@ -507,7 +507,7 @@ static int add_socket_to_server(grpc_udp_server* s, int fd, int grpc_udp_server_add_port(grpc_udp_server* s, const grpc_resolved_address* addr, - size_t rcv_buf_size, size_t snd_buf_size, + int rcv_buf_size, int snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h index ec18716f39..c1aa49f15d 100644 --- a/src/core/lib/iomgr/udp_server.h +++ b/src/core/lib/iomgr/udp_server.h @@ -68,7 +68,7 @@ int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index); all of the multiple socket port matching logic in one place */ int grpc_udp_server_add_port(grpc_udp_server* s, const grpc_resolved_address* addr, - size_t rcv_buf_size, size_t snd_buf_size, + int rcv_buf_size, int snd_buf_size, grpc_udp_server_start_cb start_cb, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc index 5245840ba9..09f0283013 100644 --- a/test/core/iomgr/udp_server_test.cc +++ b/test/core/iomgr/udp_server_test.cc @@ -51,8 +51,8 @@ static int g_number_of_bytes_read = 0; static int g_number_of_orphan_calls = 0; static int g_number_of_starts = 0; -size_t rcv_buf_size = 1024; -size_t snd_buf_size = 1024; +int rcv_buf_size = 1024; +int snd_buf_size = 1024; static void on_start(grpc_fd* emfd, void* user_data) { g_number_of_starts++; } -- cgit v1.2.3 From 951f84aea00a1f8a65cf160d7d8f342c30593000 Mon Sep 17 00:00:00 2001 From: "David G. Quintas" Date: Thu, 11 Jan 2018 15:32:34 -0800 Subject: Revert "Set error status correctly on server side" --- CMakeLists.txt | 2 - Makefile | 2 - gRPC-Core.podspec | 1 - grpc.gyp | 2 - src/core/lib/surface/call.cc | 5 +- test/core/end2end/end2end_nosec_tests.cc | 8 - test/core/end2end/end2end_tests.cc | 8 - test/core/end2end/gen_build_yaml.py | 1 - test/core/end2end/generate_tests.bzl | 1 - test/core/end2end/tests/filter_status_code.cc | 353 --------- tools/run_tests/generated/sources_and_headers.json | 2 - tools/run_tests/generated/tests.json | 839 +-------------------- 12 files changed, 27 insertions(+), 1197 deletions(-) delete mode 100644 test/core/end2end/tests/filter_status_code.cc (limited to 'test') diff --git a/CMakeLists.txt b/CMakeLists.txt index 78ccfb2132..deca1b3f75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4609,7 +4609,6 @@ add_library(end2end_tests test/core/end2end/tests/filter_call_init_fails.cc test/core/end2end/tests/filter_causes_close.cc test/core/end2end/tests/filter_latency.cc - test/core/end2end/tests/filter_status_code.cc test/core/end2end/tests/graceful_server_shutdown.cc test/core/end2end/tests/high_initial_seqno.cc test/core/end2end/tests/hpack_size.cc @@ -4711,7 +4710,6 @@ add_library(end2end_nosec_tests test/core/end2end/tests/filter_call_init_fails.cc test/core/end2end/tests/filter_causes_close.cc test/core/end2end/tests/filter_latency.cc - test/core/end2end/tests/filter_status_code.cc test/core/end2end/tests/graceful_server_shutdown.cc test/core/end2end/tests/high_initial_seqno.cc test/core/end2end/tests/hpack_size.cc diff --git a/Makefile b/Makefile index f50163efdc..499aca56f6 100644 --- a/Makefile +++ b/Makefile @@ -8552,7 +8552,6 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/filter_call_init_fails.cc \ test/core/end2end/tests/filter_causes_close.cc \ test/core/end2end/tests/filter_latency.cc \ - test/core/end2end/tests/filter_status_code.cc \ test/core/end2end/tests/graceful_server_shutdown.cc \ test/core/end2end/tests/high_initial_seqno.cc \ test/core/end2end/tests/hpack_size.cc \ @@ -8651,7 +8650,6 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/filter_call_init_fails.cc \ test/core/end2end/tests/filter_causes_close.cc \ test/core/end2end/tests/filter_latency.cc \ - test/core/end2end/tests/filter_status_code.cc \ test/core/end2end/tests/graceful_server_shutdown.cc \ test/core/end2end/tests/high_initial_seqno.cc \ test/core/end2end/tests/hpack_size.cc \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 358fad3d98..fcabd62c85 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1039,7 +1039,6 @@ Pod::Spec.new do |s| 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', - 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', diff --git a/grpc.gyp b/grpc.gyp index 281fbfa8a6..06da3a758f 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -2381,7 +2381,6 @@ 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', - 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', @@ -2454,7 +2453,6 @@ 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', - 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d677576c14..a457aaa7a2 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1851,9 +1851,8 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, { grpc_error* override_error = GRPC_ERROR_NONE; if (op->data.send_status_from_server.status != GRPC_STATUS_OK) { - override_error = - error_from_status(op->data.send_status_from_server.status, - "Returned non-ok status"); + override_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Error from server send status"); } if (op->data.send_status_from_server.status_details != nullptr) { call->send_extra_metadata[1].md = grpc_mdelem_from_slices( diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc index 6318550ad8..3236feea56 100644 --- a/test/core/end2end/end2end_nosec_tests.cc +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -68,8 +68,6 @@ extern void filter_causes_close(grpc_end2end_test_config config); extern void filter_causes_close_pre_init(void); extern void filter_latency(grpc_end2end_test_config config); extern void filter_latency_pre_init(void); -extern void filter_status_code(grpc_end2end_test_config config); -extern void filter_status_code_pre_init(void); extern void graceful_server_shutdown(grpc_end2end_test_config config); extern void graceful_server_shutdown_pre_init(void); extern void high_initial_seqno(grpc_end2end_test_config config); @@ -172,7 +170,6 @@ void grpc_end2end_tests_pre_init(void) { filter_call_init_fails_pre_init(); filter_causes_close_pre_init(); filter_latency_pre_init(); - filter_status_code_pre_init(); graceful_server_shutdown_pre_init(); high_initial_seqno_pre_init(); hpack_size_pre_init(); @@ -240,7 +237,6 @@ void grpc_end2end_tests(int argc, char **argv, filter_call_init_fails(config); filter_causes_close(config); filter_latency(config); - filter_status_code(config); graceful_server_shutdown(config); high_initial_seqno(config); hpack_size(config); @@ -360,10 +356,6 @@ void grpc_end2end_tests(int argc, char **argv, filter_latency(config); continue; } - if (0 == strcmp("filter_status_code", argv[i])) { - filter_status_code(config); - continue; - } if (0 == strcmp("graceful_server_shutdown", argv[i])) { graceful_server_shutdown(config); continue; diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index 9d8dfd6723..ca9443b642 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -70,8 +70,6 @@ extern void filter_causes_close(grpc_end2end_test_config config); extern void filter_causes_close_pre_init(void); extern void filter_latency(grpc_end2end_test_config config); extern void filter_latency_pre_init(void); -extern void filter_status_code(grpc_end2end_test_config config); -extern void filter_status_code_pre_init(void); extern void graceful_server_shutdown(grpc_end2end_test_config config); extern void graceful_server_shutdown_pre_init(void); extern void high_initial_seqno(grpc_end2end_test_config config); @@ -175,7 +173,6 @@ void grpc_end2end_tests_pre_init(void) { filter_call_init_fails_pre_init(); filter_causes_close_pre_init(); filter_latency_pre_init(); - filter_status_code_pre_init(); graceful_server_shutdown_pre_init(); high_initial_seqno_pre_init(); hpack_size_pre_init(); @@ -244,7 +241,6 @@ void grpc_end2end_tests(int argc, char **argv, filter_call_init_fails(config); filter_causes_close(config); filter_latency(config); - filter_status_code(config); graceful_server_shutdown(config); high_initial_seqno(config); hpack_size(config); @@ -368,10 +364,6 @@ void grpc_end2end_tests(int argc, char **argv, filter_latency(config); continue; } - if (0 == strcmp("filter_status_code", argv[i])) { - filter_status_code(config); - continue; - } if (0 == strcmp("graceful_server_shutdown", argv[i])) { graceful_server_shutdown(config); continue; diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index e7cf97b2d0..7c8e7f420a 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -101,7 +101,6 @@ END2END_TESTS = { 'filter_causes_close': default_test_options._replace(cpu_cost=LOWCPU), 'filter_call_init_fails': default_test_options, 'filter_latency': default_test_options._replace(cpu_cost=LOWCPU), - 'filter_status_code': default_test_options._replace(cpu_cost=LOWCPU), 'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU,exclude_inproc=True), 'hpack_size': default_test_options._replace(proxyable=False, traceable=False, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 1d759e1ecb..b9a42bdb88 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -146,7 +146,6 @@ END2END_TESTS = { 'trailing_metadata': test_options(), 'authority_not_supported': test_options(), 'filter_latency': test_options(), - 'filter_status_code': test_options(), 'workaround_cronet_compression': test_options(), 'write_buffering': test_options(needs_write_buffering=True), 'write_buffering_at_end': test_options(needs_write_buffering=True), diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc deleted file mode 100644 index 261ddd93ec..0000000000 --- a/test/core/end2end/tests/filter_status_code.cc +++ /dev/null @@ -1,353 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/surface/channel_init.h" -#include "test/core/end2end/cq_verifier.h" - -static bool g_enable_filter = false; -static gpr_mu g_mu; -static bool g_client_code_recv; -static bool g_server_code_recv; -static gpr_cv g_client_code_cv; -static gpr_cv g_server_code_cv; -static grpc_status_code g_client_status_code; -static grpc_status_code g_server_status_code; - -static void* tag(intptr_t t) { return (void*)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char* test_name, - grpc_channel_args* client_args, - grpc_channel_args* server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_server(&f, server_args); - config.init_client(&f, client_args); - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue* cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture* f) { - if (!f->server) return; - grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), - nullptr) - .type == GRPC_OP_COMPLETE); - grpc_server_destroy(f->server); - f->server = nullptr; -} - -static void shutdown_client(grpc_end2end_test_fixture* f) { - if (!f->client) return; - grpc_channel_destroy(f->client); - f->client = nullptr; -} - -static void end_test(grpc_end2end_test_fixture* f) { - shutdown_server(f); - shutdown_client(f); - - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -// Simple request via a server filter that saves the reported status code. -static void test_request(grpc_end2end_test_config config) { - grpc_call* c; - grpc_call* s; - grpc_end2end_test_fixture f = - begin_test(config, "filter_status_code", nullptr, nullptr); - cq_verifier* cqv = cq_verifier_create(f.cq); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_mu_lock(&g_mu); - g_client_status_code = GRPC_STATUS_OK; - g_server_status_code = GRPC_STATUS_OK; - gpr_mu_unlock(&g_mu); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr", config), deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = - grpc_server_request_call(f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_string = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(s); - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); - - // Perform checks after test tear-down - // Guards against the case that there's outstanding channel-related work on a - // call prior to verification - // TODO(https://github.com/grpc/grpc/issues/13915) enable this for windows -#ifndef GPR_WINDOWS - gpr_mu_lock(&g_mu); - if (!g_client_code_recv) { - GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3))); - } - if (!g_server_code_recv) { - GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3))); - } - GPR_ASSERT(g_client_status_code == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(g_server_status_code == GRPC_STATUS_UNIMPLEMENTED); - gpr_mu_unlock(&g_mu); -#endif // GPR_WINDOWS -} - -/******************************************************************************* - * Test status_code filter - */ - -static grpc_error* init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { - return GRPC_ERROR_NONE; -} - -static void client_destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* ignored) { - gpr_mu_lock(&g_mu); - g_client_status_code = final_info->final_status; - g_client_code_recv = true; - gpr_cv_signal(&g_client_code_cv); - gpr_mu_unlock(&g_mu); -} - -static void server_destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* ignored) { - gpr_mu_lock(&g_mu); - g_server_status_code = final_info->final_status; - g_server_code_recv = true; - gpr_cv_signal(&g_server_code_cv); - gpr_mu_unlock(&g_mu); -} - -static grpc_error* init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { - return GRPC_ERROR_NONE; -} - -static void destroy_channel_elem(grpc_channel_element* elem) {} - -static const grpc_channel_filter test_client_filter = { - grpc_call_next_op, - grpc_channel_next_op, - 0, - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - client_destroy_call_elem, - 0, - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "client_filter_status_code"}; - -static const grpc_channel_filter test_server_filter = { - grpc_call_next_op, - grpc_channel_next_op, - 0, - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - server_destroy_call_elem, - 0, - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "server_filter_status_code"}; - -/******************************************************************************* - * Registration - */ - -static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { - grpc_channel_filter* filter = (grpc_channel_filter*)arg; - if (g_enable_filter) { - // Want to add the filter as close to the end as possible, to make - // sure that all of the filters work well together. However, we - // can't add it at the very end, because the - // connected_channel/client_channel filter must be the last one. - // So we add it right before the last one. - grpc_channel_stack_builder_iterator* it = - grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); - const bool retval = grpc_channel_stack_builder_add_filter_before( - it, filter, nullptr, nullptr); - grpc_channel_stack_builder_iterator_destroy(it); - return retval; - } else { - return true; - } -} - -static void init_plugin(void) { - gpr_mu_init(&g_mu); - gpr_cv_init(&g_client_code_cv); - gpr_cv_init(&g_server_code_cv); - g_client_code_recv = false; - g_server_code_recv = false; - - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_server_filter); -} - -static void destroy_plugin(void) { - gpr_cv_destroy(&g_client_code_cv); - gpr_cv_destroy(&g_server_code_cv); - gpr_mu_destroy(&g_mu); -} - -void filter_status_code(grpc_end2end_test_config config) { - g_enable_filter = true; - test_request(config); - g_enable_filter = false; -} - -void filter_status_code_pre_init(void) { - grpc_register_plugin(init_plugin, destroy_plugin); -} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 51f0ac7ca6..7e7963916c 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -7635,7 +7635,6 @@ "test/core/end2end/tests/filter_call_init_fails.cc", "test/core/end2end/tests/filter_causes_close.cc", "test/core/end2end/tests/filter_latency.cc", - "test/core/end2end/tests/filter_status_code.cc", "test/core/end2end/tests/graceful_server_shutdown.cc", "test/core/end2end/tests/high_initial_seqno.cc", "test/core/end2end/tests/hpack_size.cc", @@ -7717,7 +7716,6 @@ "test/core/end2end/tests/filter_call_init_fails.cc", "test/core/end2end/tests/filter_causes_close.cc", "test/core/end2end/tests/filter_latency.cc", - "test/core/end2end/tests/filter_status_code.cc", "test/core/end2end/tests/graceful_server_shutdown.cc", "test/core/end2end/tests/high_initial_seqno.cc", "test/core/end2end/tests/hpack_size.cc", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 6b83cecd41..04345bfb86 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -6821,29 +6821,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_census_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -8182,29 +8159,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_compress_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -9500,28 +9454,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_fakesec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -10728,29 +10660,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_fd_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -12018,29 +11927,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -13297,25 +13183,6 @@ "linux" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "linux" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_full+pipe_test", - "platforms": [ - "linux" - ] - }, { "args": [ "graceful_server_shutdown" @@ -14500,29 +14367,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+trace_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -15815,29 +15659,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+workarounds_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -17194,30 +17015,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_http_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -18616,29 +18413,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_load_reporting_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -19995,30 +19769,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_oauth2_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -21341,7 +21091,7 @@ }, { "args": [ - "filter_status_code" + "graceful_server_shutdown" ], "ci_platforms": [ "windows", @@ -21365,7 +21115,7 @@ }, { "args": [ - "graceful_server_shutdown" + "high_initial_seqno" ], "ci_platforms": [ "windows", @@ -21389,14 +21139,14 @@ }, { "args": [ - "high_initial_seqno" + "idempotent_request" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -21413,7 +21163,7 @@ }, { "args": [ - "idempotent_request" + "invoke_large_request" ], "ci_platforms": [ "windows", @@ -21437,7 +21187,7 @@ }, { "args": [ - "invoke_large_request" + "large_metadata" ], "ci_platforms": [ "windows", @@ -21461,7 +21211,7 @@ }, { "args": [ - "large_metadata" + "load_reporting_hook" ], "ci_platforms": [ "windows", @@ -21485,14 +21235,14 @@ }, { "args": [ - "load_reporting_hook" + "max_connection_age" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -21509,31 +21259,7 @@ }, { "args": [ - "max_connection_age" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "max_message_length" + "max_message_length" ], "ci_platforms": [ "windows", @@ -22467,30 +22193,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -23715,30 +23417,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair+trace_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -24923,32 +24601,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -26295,29 +25947,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_ssl_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -27602,30 +27231,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_ssl_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -28783,29 +28388,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_uds_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -30002,29 +29584,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "inproc_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "high_initial_seqno" @@ -31062,29 +30621,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_census_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -32400,29 +31936,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_compress_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -33623,7 +33136,7 @@ }, { "args": [ - "filter_status_code" + "graceful_server_shutdown" ], "ci_platforms": [ "linux", @@ -33646,7 +33159,7 @@ }, { "args": [ - "graceful_server_shutdown" + "high_initial_seqno" ], "ci_platforms": [ "linux", @@ -33669,7 +33182,7 @@ }, { "args": [ - "high_initial_seqno" + "hpack_size" ], "ci_platforms": [ "linux", @@ -33692,14 +33205,14 @@ }, { "args": [ - "hpack_size" + "idempotent_request" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33715,7 +33228,7 @@ }, { "args": [ - "idempotent_request" + "invoke_large_request" ], "ci_platforms": [ "linux", @@ -33738,14 +33251,14 @@ }, { "args": [ - "invoke_large_request" + "keepalive_timeout" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33761,14 +33274,14 @@ }, { "args": [ - "keepalive_timeout" + "large_metadata" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33784,7 +33297,7 @@ }, { "args": [ - "large_metadata" + "load_reporting_hook" ], "ci_platforms": [ "linux", @@ -33807,14 +33320,14 @@ }, { "args": [ - "load_reporting_hook" + "max_concurrent_streams" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33830,7 +33343,7 @@ }, { "args": [ - "max_concurrent_streams" + "max_connection_age" ], "ci_platforms": [ "linux", @@ -33853,30 +33366,7 @@ }, { "args": [ - "max_connection_age" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_fd_nosec_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "max_message_length" + "max_message_length" ], "ci_platforms": [ "linux", @@ -34888,29 +34378,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -36148,25 +35615,6 @@ "linux" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "linux" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_full+pipe_nosec_test", - "platforms": [ - "linux" - ] - }, { "args": [ "graceful_server_shutdown" @@ -37328,29 +36776,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+trace_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -38620,29 +38045,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+workarounds_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -39975,30 +39377,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_http_proxy_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -41374,29 +40752,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_load_reporting_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -42657,30 +42012,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_proxy_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -43761,30 +43092,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -44985,30 +44292,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair+trace_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -46167,32 +45450,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -47491,29 +46748,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_uds_nosec_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "graceful_server_shutdown" @@ -48687,29 +47921,6 @@ "posix" ] }, - { - "args": [ - "filter_status_code" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "inproc_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "high_initial_seqno" -- cgit v1.2.3 From b353297b4394a6c5fadd04ce778bed480d6d5782 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 11 Jan 2018 20:25:30 -0800 Subject: Revert "Revert "Set error status correctly on server side"" This reverts commit 951f84aea00a1f8a65cf160d7d8f342c30593000. --- CMakeLists.txt | 2 + Makefile | 2 + gRPC-Core.podspec | 1 + grpc.gyp | 2 + src/core/lib/surface/call.cc | 5 +- test/core/end2end/end2end_nosec_tests.cc | 8 + test/core/end2end/end2end_tests.cc | 8 + test/core/end2end/gen_build_yaml.py | 1 + test/core/end2end/generate_tests.bzl | 1 + test/core/end2end/tests/filter_status_code.cc | 353 +++++++++ tools/run_tests/generated/sources_and_headers.json | 2 + tools/run_tests/generated/tests.json | 839 ++++++++++++++++++++- 12 files changed, 1197 insertions(+), 27 deletions(-) create mode 100644 test/core/end2end/tests/filter_status_code.cc (limited to 'test') diff --git a/CMakeLists.txt b/CMakeLists.txt index deca1b3f75..78ccfb2132 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4609,6 +4609,7 @@ add_library(end2end_tests test/core/end2end/tests/filter_call_init_fails.cc test/core/end2end/tests/filter_causes_close.cc test/core/end2end/tests/filter_latency.cc + test/core/end2end/tests/filter_status_code.cc test/core/end2end/tests/graceful_server_shutdown.cc test/core/end2end/tests/high_initial_seqno.cc test/core/end2end/tests/hpack_size.cc @@ -4710,6 +4711,7 @@ add_library(end2end_nosec_tests test/core/end2end/tests/filter_call_init_fails.cc test/core/end2end/tests/filter_causes_close.cc test/core/end2end/tests/filter_latency.cc + test/core/end2end/tests/filter_status_code.cc test/core/end2end/tests/graceful_server_shutdown.cc test/core/end2end/tests/high_initial_seqno.cc test/core/end2end/tests/hpack_size.cc diff --git a/Makefile b/Makefile index 499aca56f6..f50163efdc 100644 --- a/Makefile +++ b/Makefile @@ -8552,6 +8552,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/filter_call_init_fails.cc \ test/core/end2end/tests/filter_causes_close.cc \ test/core/end2end/tests/filter_latency.cc \ + test/core/end2end/tests/filter_status_code.cc \ test/core/end2end/tests/graceful_server_shutdown.cc \ test/core/end2end/tests/high_initial_seqno.cc \ test/core/end2end/tests/hpack_size.cc \ @@ -8650,6 +8651,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/filter_call_init_fails.cc \ test/core/end2end/tests/filter_causes_close.cc \ test/core/end2end/tests/filter_latency.cc \ + test/core/end2end/tests/filter_status_code.cc \ test/core/end2end/tests/graceful_server_shutdown.cc \ test/core/end2end/tests/high_initial_seqno.cc \ test/core/end2end/tests/hpack_size.cc \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index fcabd62c85..358fad3d98 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1039,6 +1039,7 @@ Pod::Spec.new do |s| 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', + 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', diff --git a/grpc.gyp b/grpc.gyp index 06da3a758f..281fbfa8a6 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -2381,6 +2381,7 @@ 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', + 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', @@ -2453,6 +2454,7 @@ 'test/core/end2end/tests/filter_call_init_fails.cc', 'test/core/end2end/tests/filter_causes_close.cc', 'test/core/end2end/tests/filter_latency.cc', + 'test/core/end2end/tests/filter_status_code.cc', 'test/core/end2end/tests/graceful_server_shutdown.cc', 'test/core/end2end/tests/high_initial_seqno.cc', 'test/core/end2end/tests/hpack_size.cc', diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index a457aaa7a2..d677576c14 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1851,8 +1851,9 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, { grpc_error* override_error = GRPC_ERROR_NONE; if (op->data.send_status_from_server.status != GRPC_STATUS_OK) { - override_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error from server send status"); + override_error = + error_from_status(op->data.send_status_from_server.status, + "Returned non-ok status"); } if (op->data.send_status_from_server.status_details != nullptr) { call->send_extra_metadata[1].md = grpc_mdelem_from_slices( diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc index 3236feea56..6318550ad8 100644 --- a/test/core/end2end/end2end_nosec_tests.cc +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -68,6 +68,8 @@ extern void filter_causes_close(grpc_end2end_test_config config); extern void filter_causes_close_pre_init(void); extern void filter_latency(grpc_end2end_test_config config); extern void filter_latency_pre_init(void); +extern void filter_status_code(grpc_end2end_test_config config); +extern void filter_status_code_pre_init(void); extern void graceful_server_shutdown(grpc_end2end_test_config config); extern void graceful_server_shutdown_pre_init(void); extern void high_initial_seqno(grpc_end2end_test_config config); @@ -170,6 +172,7 @@ void grpc_end2end_tests_pre_init(void) { filter_call_init_fails_pre_init(); filter_causes_close_pre_init(); filter_latency_pre_init(); + filter_status_code_pre_init(); graceful_server_shutdown_pre_init(); high_initial_seqno_pre_init(); hpack_size_pre_init(); @@ -237,6 +240,7 @@ void grpc_end2end_tests(int argc, char **argv, filter_call_init_fails(config); filter_causes_close(config); filter_latency(config); + filter_status_code(config); graceful_server_shutdown(config); high_initial_seqno(config); hpack_size(config); @@ -356,6 +360,10 @@ void grpc_end2end_tests(int argc, char **argv, filter_latency(config); continue; } + if (0 == strcmp("filter_status_code", argv[i])) { + filter_status_code(config); + continue; + } if (0 == strcmp("graceful_server_shutdown", argv[i])) { graceful_server_shutdown(config); continue; diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index ca9443b642..9d8dfd6723 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -70,6 +70,8 @@ extern void filter_causes_close(grpc_end2end_test_config config); extern void filter_causes_close_pre_init(void); extern void filter_latency(grpc_end2end_test_config config); extern void filter_latency_pre_init(void); +extern void filter_status_code(grpc_end2end_test_config config); +extern void filter_status_code_pre_init(void); extern void graceful_server_shutdown(grpc_end2end_test_config config); extern void graceful_server_shutdown_pre_init(void); extern void high_initial_seqno(grpc_end2end_test_config config); @@ -173,6 +175,7 @@ void grpc_end2end_tests_pre_init(void) { filter_call_init_fails_pre_init(); filter_causes_close_pre_init(); filter_latency_pre_init(); + filter_status_code_pre_init(); graceful_server_shutdown_pre_init(); high_initial_seqno_pre_init(); hpack_size_pre_init(); @@ -241,6 +244,7 @@ void grpc_end2end_tests(int argc, char **argv, filter_call_init_fails(config); filter_causes_close(config); filter_latency(config); + filter_status_code(config); graceful_server_shutdown(config); high_initial_seqno(config); hpack_size(config); @@ -364,6 +368,10 @@ void grpc_end2end_tests(int argc, char **argv, filter_latency(config); continue; } + if (0 == strcmp("filter_status_code", argv[i])) { + filter_status_code(config); + continue; + } if (0 == strcmp("graceful_server_shutdown", argv[i])) { graceful_server_shutdown(config); continue; diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 7c8e7f420a..e7cf97b2d0 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -101,6 +101,7 @@ END2END_TESTS = { 'filter_causes_close': default_test_options._replace(cpu_cost=LOWCPU), 'filter_call_init_fails': default_test_options, 'filter_latency': default_test_options._replace(cpu_cost=LOWCPU), + 'filter_status_code': default_test_options._replace(cpu_cost=LOWCPU), 'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU,exclude_inproc=True), 'hpack_size': default_test_options._replace(proxyable=False, traceable=False, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index b9a42bdb88..1d759e1ecb 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -146,6 +146,7 @@ END2END_TESTS = { 'trailing_metadata': test_options(), 'authority_not_supported': test_options(), 'filter_latency': test_options(), + 'filter_status_code': test_options(), 'workaround_cronet_compression': test_options(), 'write_buffering': test_options(needs_write_buffering=True), 'write_buffering_at_end': test_options(needs_write_buffering=True), diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc new file mode 100644 index 0000000000..261ddd93ec --- /dev/null +++ b/test/core/end2end/tests/filter_status_code.cc @@ -0,0 +1,353 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/channel_init.h" +#include "test/core/end2end/cq_verifier.h" + +static bool g_enable_filter = false; +static gpr_mu g_mu; +static bool g_client_code_recv; +static bool g_server_code_recv; +static gpr_cv g_client_code_cv; +static gpr_cv g_server_code_cv; +static grpc_status_code g_client_status_code; +static grpc_status_code g_server_status_code; + +static void* tag(intptr_t t) { return (void*)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char* test_name, + grpc_channel_args* client_args, + grpc_channel_args* server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture* f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = nullptr; +} + +static void shutdown_client(grpc_end2end_test_fixture* f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = nullptr; +} + +static void end_test(grpc_end2end_test_fixture* f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Simple request via a server filter that saves the reported status code. +static void test_request(grpc_end2end_test_config config) { + grpc_call* c; + grpc_call* s; + grpc_end2end_test_fixture f = + begin_test(config, "filter_status_code", nullptr, nullptr); + cq_verifier* cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op* op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_mu_lock(&g_mu); + g_client_status_code = GRPC_STATUS_OK; + g_server_status_code = GRPC_STATUS_OK; + gpr_mu_unlock(&g_mu); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr", config), deadline, nullptr); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = nullptr; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; + grpc_slice status_string = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_string; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_unref(s); + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); + + // Perform checks after test tear-down + // Guards against the case that there's outstanding channel-related work on a + // call prior to verification + // TODO(https://github.com/grpc/grpc/issues/13915) enable this for windows +#ifndef GPR_WINDOWS + gpr_mu_lock(&g_mu); + if (!g_client_code_recv) { + GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, + grpc_timeout_seconds_to_deadline(3))); + } + if (!g_server_code_recv) { + GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, + grpc_timeout_seconds_to_deadline(3))); + } + GPR_ASSERT(g_client_status_code == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(g_server_status_code == GRPC_STATUS_UNIMPLEMENTED); + gpr_mu_unlock(&g_mu); +#endif // GPR_WINDOWS +} + +/******************************************************************************* + * Test status_code filter + */ + +static grpc_error* init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { + return GRPC_ERROR_NONE; +} + +static void client_destroy_call_elem(grpc_call_element* elem, + const grpc_call_final_info* final_info, + grpc_closure* ignored) { + gpr_mu_lock(&g_mu); + g_client_status_code = final_info->final_status; + g_client_code_recv = true; + gpr_cv_signal(&g_client_code_cv); + gpr_mu_unlock(&g_mu); +} + +static void server_destroy_call_elem(grpc_call_element* elem, + const grpc_call_final_info* final_info, + grpc_closure* ignored) { + gpr_mu_lock(&g_mu); + g_server_status_code = final_info->final_status; + g_server_code_recv = true; + gpr_cv_signal(&g_server_code_cv); + gpr_mu_unlock(&g_mu); +} + +static grpc_error* init_channel_elem(grpc_channel_element* elem, + grpc_channel_element_args* args) { + return GRPC_ERROR_NONE; +} + +static void destroy_channel_elem(grpc_channel_element* elem) {} + +static const grpc_channel_filter test_client_filter = { + grpc_call_next_op, + grpc_channel_next_op, + 0, + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + client_destroy_call_elem, + 0, + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "client_filter_status_code"}; + +static const grpc_channel_filter test_server_filter = { + grpc_call_next_op, + grpc_channel_next_op, + 0, + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + server_destroy_call_elem, + 0, + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "server_filter_status_code"}; + +/******************************************************************************* + * Registration + */ + +static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { + grpc_channel_filter* filter = (grpc_channel_filter*)arg; + if (g_enable_filter) { + // Want to add the filter as close to the end as possible, to make + // sure that all of the filters work well together. However, we + // can't add it at the very end, because the + // connected_channel/client_channel filter must be the last one. + // So we add it right before the last one. + grpc_channel_stack_builder_iterator* it = + grpc_channel_stack_builder_create_iterator_at_last(builder); + GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); + const bool retval = grpc_channel_stack_builder_add_filter_before( + it, filter, nullptr, nullptr); + grpc_channel_stack_builder_iterator_destroy(it); + return retval; + } else { + return true; + } +} + +static void init_plugin(void) { + gpr_mu_init(&g_mu); + gpr_cv_init(&g_client_code_cv); + gpr_cv_init(&g_server_code_cv); + g_client_code_recv = false; + g_server_code_recv = false; + + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + maybe_add_filter, + (void*)&test_client_filter); + grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, + maybe_add_filter, + (void*)&test_client_filter); + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + maybe_add_filter, + (void*)&test_server_filter); +} + +static void destroy_plugin(void) { + gpr_cv_destroy(&g_client_code_cv); + gpr_cv_destroy(&g_server_code_cv); + gpr_mu_destroy(&g_mu); +} + +void filter_status_code(grpc_end2end_test_config config) { + g_enable_filter = true; + test_request(config); + g_enable_filter = false; +} + +void filter_status_code_pre_init(void) { + grpc_register_plugin(init_plugin, destroy_plugin); +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7e7963916c..51f0ac7ca6 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -7635,6 +7635,7 @@ "test/core/end2end/tests/filter_call_init_fails.cc", "test/core/end2end/tests/filter_causes_close.cc", "test/core/end2end/tests/filter_latency.cc", + "test/core/end2end/tests/filter_status_code.cc", "test/core/end2end/tests/graceful_server_shutdown.cc", "test/core/end2end/tests/high_initial_seqno.cc", "test/core/end2end/tests/hpack_size.cc", @@ -7716,6 +7717,7 @@ "test/core/end2end/tests/filter_call_init_fails.cc", "test/core/end2end/tests/filter_causes_close.cc", "test/core/end2end/tests/filter_latency.cc", + "test/core/end2end/tests/filter_status_code.cc", "test/core/end2end/tests/graceful_server_shutdown.cc", "test/core/end2end/tests/high_initial_seqno.cc", "test/core/end2end/tests/hpack_size.cc", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 04345bfb86..6b83cecd41 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -6821,6 +6821,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -8159,6 +8182,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -9454,6 +9500,28 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -10660,6 +10728,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -11927,6 +12018,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -13183,6 +13297,25 @@ "linux" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, { "args": [ "graceful_server_shutdown" @@ -14367,6 +14500,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -15659,6 +15815,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+workarounds_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -17015,6 +17194,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -18413,6 +18616,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -19769,6 +19995,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -21091,7 +21341,7 @@ }, { "args": [ - "graceful_server_shutdown" + "filter_status_code" ], "ci_platforms": [ "windows", @@ -21115,7 +21365,7 @@ }, { "args": [ - "high_initial_seqno" + "graceful_server_shutdown" ], "ci_platforms": [ "windows", @@ -21139,14 +21389,14 @@ }, { "args": [ - "idempotent_request" + "high_initial_seqno" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -21163,7 +21413,7 @@ }, { "args": [ - "invoke_large_request" + "idempotent_request" ], "ci_platforms": [ "windows", @@ -21187,7 +21437,7 @@ }, { "args": [ - "large_metadata" + "invoke_large_request" ], "ci_platforms": [ "windows", @@ -21211,7 +21461,7 @@ }, { "args": [ - "load_reporting_hook" + "large_metadata" ], "ci_platforms": [ "windows", @@ -21235,14 +21485,14 @@ }, { "args": [ - "max_connection_age" + "load_reporting_hook" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -21259,7 +21509,31 @@ }, { "args": [ - "max_message_length" + "max_connection_age" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_message_length" ], "ci_platforms": [ "windows", @@ -22193,6 +22467,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -23417,6 +23715,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -24601,6 +24923,32 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -25947,6 +26295,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -27231,6 +27602,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_ssl_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -28388,6 +28783,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -29584,6 +30002,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "inproc_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "high_initial_seqno" @@ -30621,6 +31062,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -31936,6 +32400,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -33136,7 +33623,7 @@ }, { "args": [ - "graceful_server_shutdown" + "filter_status_code" ], "ci_platforms": [ "linux", @@ -33159,7 +33646,7 @@ }, { "args": [ - "high_initial_seqno" + "graceful_server_shutdown" ], "ci_platforms": [ "linux", @@ -33182,7 +33669,7 @@ }, { "args": [ - "hpack_size" + "high_initial_seqno" ], "ci_platforms": [ "linux", @@ -33205,14 +33692,14 @@ }, { "args": [ - "idempotent_request" + "hpack_size" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33228,7 +33715,7 @@ }, { "args": [ - "invoke_large_request" + "idempotent_request" ], "ci_platforms": [ "linux", @@ -33251,14 +33738,14 @@ }, { "args": [ - "keepalive_timeout" + "invoke_large_request" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33274,14 +33761,14 @@ }, { "args": [ - "large_metadata" + "keepalive_timeout" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33297,7 +33784,7 @@ }, { "args": [ - "load_reporting_hook" + "large_metadata" ], "ci_platforms": [ "linux", @@ -33320,14 +33807,14 @@ }, { "args": [ - "max_concurrent_streams" + "load_reporting_hook" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -33343,7 +33830,7 @@ }, { "args": [ - "max_connection_age" + "max_concurrent_streams" ], "ci_platforms": [ "linux", @@ -33366,7 +33853,30 @@ }, { "args": [ - "max_message_length" + "max_connection_age" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_message_length" ], "ci_platforms": [ "linux", @@ -34378,6 +34888,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -35615,6 +36148,25 @@ "linux" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, { "args": [ "graceful_server_shutdown" @@ -36776,6 +37328,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -38045,6 +38620,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+workarounds_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -39377,6 +39975,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -40752,6 +41374,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -42012,6 +42657,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -43092,6 +43761,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -44292,6 +44985,30 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -45450,6 +46167,32 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -46748,6 +47491,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "graceful_server_shutdown" @@ -47921,6 +48687,29 @@ "posix" ] }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "inproc_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "high_initial_seqno" -- cgit v1.2.3 From 5ca71f29bc3ee804c1d28ae63cbc9a9825a66d0c Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 11 Jan 2018 20:24:06 -0800 Subject: Fix issue with filter_status_code test for proxy tests. --- test/core/end2end/tests/filter_status_code.cc | 53 ++++++++++++++++++++------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'test') diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc index 261ddd93ec..61c658b95a 100644 --- a/test/core/end2end/tests/filter_status_code.cc +++ b/test/core/end2end/tests/filter_status_code.cc @@ -30,11 +30,14 @@ #include #include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" #include "test/core/end2end/cq_verifier.h" static bool g_enable_filter = false; static gpr_mu g_mu; +static grpc_call_stack* g_client_call_stack; +static grpc_call_stack* g_server_call_stack; static bool g_client_code_recv; static bool g_server_code_recv; static gpr_cv g_client_code_cv; @@ -117,6 +120,8 @@ static void test_request(grpc_end2end_test_config config) { int was_cancelled = 2; gpr_mu_lock(&g_mu); + g_client_call_stack = nullptr; + g_server_call_stack = nullptr; g_client_status_code = GRPC_STATUS_OK; g_server_status_code = GRPC_STATUS_OK; gpr_mu_unlock(&g_mu); @@ -127,6 +132,9 @@ static void test_request(grpc_end2end_test_config config) { grpc_slice_from_static_string("/foo"), get_host_override_slice("foo.test.google.fr", config), deadline, nullptr); GPR_ASSERT(c); + gpr_mu_lock(&g_mu); + g_client_call_stack = grpc_call_get_call_stack(c); + gpr_mu_unlock(&g_mu); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); @@ -168,6 +176,10 @@ static void test_request(grpc_end2end_test_config config) { CQ_EXPECT_COMPLETION(cqv, tag(101), 1); cq_verify(cqv); + gpr_mu_lock(&g_mu); + g_server_call_stack = grpc_call_get_call_stack(s); + gpr_mu_unlock(&g_mu); + memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; @@ -215,49 +227,62 @@ static void test_request(grpc_end2end_test_config config) { // Perform checks after test tear-down // Guards against the case that there's outstanding channel-related work on a // call prior to verification - // TODO(https://github.com/grpc/grpc/issues/13915) enable this for windows -#ifndef GPR_WINDOWS gpr_mu_lock(&g_mu); if (!g_client_code_recv) { GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3))); + grpc_timeout_seconds_to_deadline(3)) == 0); } if (!g_server_code_recv) { - GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3))); + GPR_ASSERT(gpr_cv_wait(&g_server_code_cv, &g_mu, + grpc_timeout_seconds_to_deadline(3)) == 0); } GPR_ASSERT(g_client_status_code == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(g_server_status_code == GRPC_STATUS_UNIMPLEMENTED); gpr_mu_unlock(&g_mu); -#endif // GPR_WINDOWS } /******************************************************************************* * Test status_code filter */ +typedef struct final_status_data { + grpc_call_stack* call; +} final_status_data; + static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { + final_status_data* data = (final_status_data*)elem->call_data; + data->call = args->call_stack; return GRPC_ERROR_NONE; } static void client_destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { + final_status_data* data = (final_status_data*)elem->call_data; gpr_mu_lock(&g_mu); - g_client_status_code = final_info->final_status; - g_client_code_recv = true; - gpr_cv_signal(&g_client_code_cv); + // Some fixtures, like proxies, will spawn intermidiate calls + // We only want the results from our explicit calls + if (data->call == g_client_call_stack) { + g_client_status_code = final_info->final_status; + g_client_code_recv = true; + gpr_cv_signal(&g_client_code_cv); + } gpr_mu_unlock(&g_mu); } static void server_destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { + final_status_data* data = (final_status_data*)elem->call_data; gpr_mu_lock(&g_mu); - g_server_status_code = final_info->final_status; - g_server_code_recv = true; - gpr_cv_signal(&g_server_code_cv); + // Some fixtures, like proxies, will spawn intermidiate calls + // We only want the results from our explicit calls + if (data->call == g_server_call_stack) { + g_server_status_code = final_info->final_status; + g_server_code_recv = true; + gpr_cv_signal(&g_server_code_cv); + } gpr_mu_unlock(&g_mu); } @@ -271,7 +296,7 @@ static void destroy_channel_elem(grpc_channel_element* elem) {} static const grpc_channel_filter test_client_filter = { grpc_call_next_op, grpc_channel_next_op, - 0, + sizeof(final_status_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, client_destroy_call_elem, @@ -284,7 +309,7 @@ static const grpc_channel_filter test_client_filter = { static const grpc_channel_filter test_server_filter = { grpc_call_next_op, grpc_channel_next_op, - 0, + sizeof(final_status_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, server_destroy_call_elem, -- cgit v1.2.3 From 148700a8ea4b1a6d7ac82f1ad504c4e1eaa4e263 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 12 Jan 2018 09:18:21 +0100 Subject: windows needs fflush after fprintf --- test/core/fling/client.cc | 2 ++ test/core/network_benchmarks/low_level_ping_pong.cc | 4 ++++ test/core/security/create_jwt.cc | 5 +++++ test/core/security/print_google_default_creds_token.cc | 2 ++ test/core/security/verify_jwt.cc | 2 ++ test/core/support/cpu_test.cc | 3 +++ test/core/support/spinlock_test.cc | 4 ++++ test/core/support/sync_test.cc | 4 ++++ test/core/support/time_test.cc | 11 +++++++++++ test/core/util/debugger_macros.cc | 2 ++ 10 files changed, 39 insertions(+) (limited to 'test') diff --git a/test/core/fling/client.cc b/test/core/fling/client.cc index 69fb6dc7c7..28e62e0e83 100644 --- a/test/core/fling/client.cc +++ b/test/core/fling/client.cc @@ -186,8 +186,10 @@ int main(int argc, char** argv) { } if (!sc.name) { fprintf(stderr, "unsupported scenario '%s'. Valid are:", scenario_name); + fflush(stderr); for (i = 0; i < GPR_ARRAY_SIZE(scenarios); i++) { fprintf(stderr, " %s", scenarios[i].name); + fflush(stderr); } return 1; } diff --git a/test/core/network_benchmarks/low_level_ping_pong.cc b/test/core/network_benchmarks/low_level_ping_pong.cc index 96b0745f52..fb982a10fd 100644 --- a/test/core/network_benchmarks/low_level_ping_pong.cc +++ b/test/core/network_benchmarks/low_level_ping_pong.cc @@ -535,6 +535,7 @@ void print_usage(char* argv0) { fprintf(stderr, " tcp: fds are endpoints of a TCP connection\n"); fprintf(stderr, " socketpair: fds come from socketpair()\n"); fprintf(stderr, " pipe: fds come from pipe()\n"); + fflush(stderr); } typedef struct test_strategy { @@ -565,6 +566,7 @@ int create_socket(const char* socket_type, fd_pair* client_fds, create_sockets_pipe(client_fds, server_fds); } else { fprintf(stderr, "Invalid socket type %s\n", socket_type); + fflush(stderr); return -1; } return 0; @@ -657,6 +659,7 @@ int main(int argc, char** argv) { } if (msg_size <= 0) { fprintf(stderr, "msg_size must be > 0\n"); + fflush(stderr); print_usage(argv[0]); return -1; } @@ -668,6 +671,7 @@ int main(int argc, char** argv) { } if (strategy == nullptr) { fprintf(stderr, "Invalid read strategy %s\n", read_strategy); + fflush(stderr); return -1; } diff --git a/test/core/security/create_jwt.cc b/test/core/security/create_jwt.cc index 867a8ba575..56ae9c891c 100644 --- a/test/core/security/create_jwt.cc +++ b/test/core/security/create_jwt.cc @@ -39,6 +39,7 @@ void create_jwt(const char* json_key_file_path, const char* service_url, grpc_slice_unref(json_key_data); if (!grpc_auth_json_key_is_valid(&key)) { fprintf(stderr, "Could not parse json key.\n"); + fflush(stderr); exit(1); } jwt = grpc_jwt_encode_and_sign( @@ -47,6 +48,7 @@ void create_jwt(const char* json_key_file_path, const char* service_url, grpc_auth_json_key_destruct(&key); if (jwt == nullptr) { fprintf(stderr, "Could not create JWT.\n"); + fflush(stderr); exit(1); } fprintf(stdout, "%s\n", jwt); @@ -72,16 +74,19 @@ int main(int argc, char** argv) { if (json_key_file_path == nullptr) { fprintf(stderr, "Missing --json_key option.\n"); + fflush(stderr); exit(1); } if (scope != nullptr) { if (service_url != nullptr) { fprintf(stderr, "Options --scope and --service_url are mutually exclusive.\n"); + fflush(stderr); exit(1); } } else if (service_url == nullptr) { fprintf(stderr, "Need one of --service_url or --scope options.\n"); + fflush(stderr); exit(1); } diff --git a/test/core/security/print_google_default_creds_token.cc b/test/core/security/print_google_default_creds_token.cc index b3742f58a8..d71116d8f6 100644 --- a/test/core/security/print_google_default_creds_token.cc +++ b/test/core/security/print_google_default_creds_token.cc @@ -45,6 +45,7 @@ static void on_metadata_response(void* arg, grpc_error* error) { synchronizer* sync = static_cast(arg); if (error != GRPC_ERROR_NONE) { fprintf(stderr, "Fetching token failed: %s\n", grpc_error_string(error)); + fflush(stderr); } else { char* token; GPR_ASSERT(sync->md_array.size == 1); @@ -81,6 +82,7 @@ int main(int argc, char** argv) { creds = grpc_google_default_credentials_create(); if (creds == nullptr) { fprintf(stderr, "\nCould not find default credentials.\n\n"); + fflush(stderr); result = 1; goto end; } diff --git a/test/core/security/verify_jwt.cc b/test/core/security/verify_jwt.cc index e039970c67..5d32ce0cdb 100644 --- a/test/core/security/verify_jwt.cc +++ b/test/core/security/verify_jwt.cc @@ -39,6 +39,7 @@ typedef struct { static void print_usage_and_exit(gpr_cmdline* cl, const char* argv0) { char* usage = gpr_cmdline_usage_string(cl, argv0); fprintf(stderr, "%s", usage); + fflush(stderr); gpr_free(usage); gpr_cmdline_destroy(cl); exit(1); @@ -62,6 +63,7 @@ static void on_jwt_verification_done(void* user_data, GPR_ASSERT(claims == nullptr); fprintf(stderr, "Verification failed with error %s\n", grpc_jwt_verifier_status_to_string(status)); + fflush(stderr); } gpr_mu_lock(sync->mu); diff --git a/test/core/support/cpu_test.cc b/test/core/support/cpu_test.cc index 334c4318e1..87cdc0fb50 100644 --- a/test/core/support/cpu_test.cc +++ b/test/core/support/cpu_test.cc @@ -119,13 +119,16 @@ static void cpu_test(void) { } gpr_mu_unlock(&ct.mu); fprintf(stderr, "Saw cores ["); + fflush(stderr); for (i = 0; i < ct.ncores; i++) { if (ct.used[i]) { fprintf(stderr, "%d,", i); + fflush(stderr); cores_seen++; } } fprintf(stderr, "] (%d/%d)\n", cores_seen, ct.ncores); + fflush(stderr); gpr_free(ct.used); } diff --git a/test/core/support/spinlock_test.cc b/test/core/support/spinlock_test.cc index 58d5fcd42b..ea0dbbf7c6 100644 --- a/test/core/support/spinlock_test.cc +++ b/test/core/support/spinlock_test.cc @@ -95,15 +95,18 @@ static void test(const char* name, void (*body)(void* m), int timeout_s, gpr_timespec deadline = gpr_time_add( start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); fprintf(stderr, "%s:", name); + fflush(stderr); while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { if (iterations < INT64_MAX / 2) iterations <<= 1; fprintf(stderr, " %ld", (long)iterations); + fflush(stderr); m = test_new(10, iterations, incr_step); test_create_threads(m, body); test_wait(m); if (m->counter != m->thread_count * m->iterations * m->incr_step) { fprintf(stderr, "counter %ld threads %d iterations %ld\n", (long)m->counter, m->thread_count, (long)m->iterations); + fflush(stderr); GPR_ASSERT(0); } test_destroy(m); @@ -111,6 +114,7 @@ static void test(const char* name, void (*body)(void* m), int timeout_s, time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, (int)time_taken.tv_nsec); + fflush(stderr); } /* Increment m->counter on each iteration; then mark thread as done. */ diff --git a/test/core/support/sync_test.cc b/test/core/support/sync_test.cc index fb7ec44754..04b9e94cbc 100644 --- a/test/core/support/sync_test.cc +++ b/test/core/support/sync_test.cc @@ -238,9 +238,11 @@ static void test(const char* name, void (*body)(void* m), gpr_timespec deadline = gpr_time_add( start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); fprintf(stderr, "%s:", name); + fflush(stderr); while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { iterations <<= 1; fprintf(stderr, " %ld", (long)iterations); + fflush(stderr); m = test_new(10, iterations, incr_step); if (extra != nullptr) { gpr_thd_id id; @@ -252,6 +254,7 @@ static void test(const char* name, void (*body)(void* m), if (m->counter != m->threads * m->iterations * m->incr_step) { fprintf(stderr, "counter %ld threads %d iterations %ld\n", (long)m->counter, m->threads, (long)m->iterations); + fflush(stderr); GPR_ASSERT(0); } test_destroy(m); @@ -259,6 +262,7 @@ static void test(const char* name, void (*body)(void* m), time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, (int)time_taken.tv_nsec); + fflush(stderr); } /* Increment m->counter on each iteration; then mark thread as done. */ diff --git a/test/core/support/time_test.cc b/test/core/support/time_test.cc index 608169274f..b2b4dce58e 100644 --- a/test/core/support/time_test.cc +++ b/test/core/support/time_test.cc @@ -66,21 +66,28 @@ static void test_values(void) { x = gpr_inf_future(GPR_CLOCK_REALTIME); fprintf(stderr, "far future "); + fflush(stderr); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); GPR_ASSERT(x.tv_sec == INT64_MAX); fprintf(stderr, "far future "); + fflush(stderr); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); + fflush(stderr); x = gpr_inf_past(GPR_CLOCK_REALTIME); fprintf(stderr, "far past "); + fflush(stderr); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); + fflush(stderr); GPR_ASSERT(x.tv_sec == INT64_MIN); fprintf(stderr, "far past "); + fflush(stderr); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); + fflush(stderr); for (i = 1; i != 1000 * 1000 * 1000; i *= 10) { x = gpr_time_from_micros(i, GPR_TIMESPAN); @@ -135,15 +142,19 @@ static void test_add_sub(void) { if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) != 0) { fprintf(stderr, "i %d j %d sum %d sumt ", i, j, sum); + fflush(stderr); ts_to_s(sumt, &to_fp, stderr); fprintf(stderr, "\n"); + fflush(stderr); GPR_ASSERT(0); } if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) != 0) { fprintf(stderr, "i %d j %d diff %d diff ", i, j, diff); + fflush(stderr); ts_to_s(sumt, &to_fp, stderr); fprintf(stderr, "\n"); + fflush(stderr); GPR_ASSERT(0); } } diff --git a/test/core/util/debugger_macros.cc b/test/core/util/debugger_macros.cc index f1e4ffd3af..bb96fc7054 100644 --- a/test/core/util/debugger_macros.cc +++ b/test/core/util/debugger_macros.cc @@ -39,6 +39,7 @@ grpc_stream* grpc_transport_stream_from_call(grpc_call* call) { grpc_subchannel_call* scc = grpc_client_channel_get_subchannel_call(el); if (scc == nullptr) { fprintf(stderr, "No subchannel-call"); + fflush(stderr); return nullptr; } cs = grpc_subchannel_call_get_call_stack(scc); @@ -46,6 +47,7 @@ grpc_stream* grpc_transport_stream_from_call(grpc_call* call) { return grpc_connected_channel_get_stream(el); } else { fprintf(stderr, "Unrecognized filter: %s", el->filter->name); + fflush(stderr); return nullptr; } } -- cgit v1.2.3 From c9ec2c0888271491eaf425721a72736392f85945 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 12 Jan 2018 10:16:22 +0100 Subject: Revert "Stop using std::thread in C++ library since it can trigger exceptions" --- include/grpc++/impl/codegen/byte_buffer.h | 4 - include/grpc++/impl/codegen/completion_queue.h | 6 +- include/grpc++/impl/codegen/method_handler_impl.h | 17 +-- include/grpc++/impl/codegen/server_context.h | 6 +- include/grpc++/server.h | 21 +-- include/grpc++/server_builder.h | 19 --- src/cpp/client/secure_credentials.cc | 14 +- src/cpp/server/create_default_thread_pool.cc | 2 +- src/cpp/server/dynamic_thread_pool.cc | 54 ++------ src/cpp/server/dynamic_thread_pool.h | 20 +-- src/cpp/server/secure_server_credentials.cc | 7 +- src/cpp/server/server_builder.cc | 7 +- src/cpp/server/server_cc.cc | 49 ++----- src/cpp/server/thread_pool_interface.h | 4 +- src/cpp/thread_manager/thread_manager.cc | 54 ++------ src/cpp/thread_manager/thread_manager.h | 29 +--- test/cpp/end2end/thread_stress_test.cc | 157 +++++++++------------- test/cpp/thread_manager/BUILD | 31 ----- test/cpp/thread_manager/thread_manager_test.cc | 8 +- 19 files changed, 133 insertions(+), 376 deletions(-) delete mode 100644 test/cpp/thread_manager/BUILD (limited to 'test') diff --git a/include/grpc++/impl/codegen/byte_buffer.h b/include/grpc++/impl/codegen/byte_buffer.h index 9c0246e617..fe73ce7a83 100644 --- a/include/grpc++/impl/codegen/byte_buffer.h +++ b/include/grpc++/impl/codegen/byte_buffer.h @@ -41,8 +41,6 @@ template class RpcMethodHandler; template class ServerStreamingHandler; -template -class ErrorMethodHandler; template class DeserializeFuncType; } // namespace internal @@ -109,8 +107,6 @@ class ByteBuffer final { friend class internal::RpcMethodHandler; template friend class internal::ServerStreamingHandler; - template - friend class internal::ErrorMethodHandler; template friend class internal::DeserializeFuncType; diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index 452eac6646..b8a7862578 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -78,8 +78,7 @@ template class ServerStreamingHandler; template class BidiStreamingHandler; -template -class ErrorMethodHandler; +class UnknownMethodHandler; template class TemplatedBidiStreamingHandler; template @@ -222,8 +221,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::ServerStreamingHandler; template friend class ::grpc::internal::TemplatedBidiStreamingHandler; - template - friend class ::grpc::internal::ErrorMethodHandler; + friend class ::grpc::internal::UnknownMethodHandler; friend class ::grpc::Server; friend class ::grpc::ServerContext; friend class ::grpc::ServerInterface; diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index 93b7826e8f..c0af4ca130 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -242,14 +242,12 @@ class SplitServerStreamingHandler ServerSplitStreamer, false>(func) {} }; -/// General method handler class for errors that prevent real method use -/// e.g., handle unknown method by returning UNIMPLEMENTED error. -template -class ErrorMethodHandler : public MethodHandler { +/// Handle unknown method by returning UNIMPLEMENTED error. +class UnknownMethodHandler : public MethodHandler { public: template static void FillOps(ServerContext* context, T* ops) { - Status status(code, ""); + Status status(StatusCode::UNIMPLEMENTED, ""); if (!context->sent_initial_metadata_) { ops->SendInitialMetadata(context->initial_metadata_, context->initial_metadata_flags()); @@ -266,18 +264,9 @@ class ErrorMethodHandler : public MethodHandler { FillOps(param.server_context, &ops); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); - // We also have to destroy any request payload in the handler parameter - ByteBuffer* payload = param.request.bbuf_ptr(); - if (payload != nullptr) { - payload->Clear(); - } } }; -typedef ErrorMethodHandler UnknownMethodHandler; -typedef ErrorMethodHandler - ResourceExhaustedHandler; - } // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index 9f20335a2a..a2d6967bf8 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -63,8 +63,7 @@ template class ServerStreamingHandler; template class BidiStreamingHandler; -template -class ErrorMethodHandler; +class UnknownMethodHandler; template class TemplatedBidiStreamingHandler; class Call; @@ -256,8 +255,7 @@ class ServerContext { friend class ::grpc::internal::ServerStreamingHandler; template friend class ::grpc::internal::TemplatedBidiStreamingHandler; - template - friend class ::grpc::internal::ErrorMethodHandler; + friend class ::grpc::internal::UnknownMethodHandler; friend class ::grpc::ClientContext; /// Prevent copying. diff --git a/include/grpc++/server.h b/include/grpc++/server.h index cf590185d1..01c4a60d21 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -35,7 +35,6 @@ #include #include #include -#include struct grpc_server; @@ -139,20 +138,10 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on /// server completion queues passed via sync_server_cqs param. - /// - /// \param thread_creator The thread creation function for the sync - /// server. Typically gpr_thd_new - /// - /// \param thread_joiner The thread joining function for the sync - /// server. Typically gpr_thd_join Server(int max_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec, - std::function - thread_creator, - std::function thread_joiner); + int min_pollers, int max_pollers, int sync_cq_timeout_msec); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the Server instance. @@ -231,14 +220,6 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { std::unique_ptr health_check_service_; bool health_check_service_disabled_; - - std::function - thread_creator_; - std::function thread_joiner_; - - // A special handler for resource exhausted in sync case - std::unique_ptr resource_exhausted_handler_; }; } // namespace grpc diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 25bbacbbc7..e2bae4b41f 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -20,7 +20,6 @@ #define GRPCXX_SERVER_BUILDER_H #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include #include -#include #include #include @@ -49,7 +47,6 @@ class Service; namespace testing { class ServerBuilderPluginTest; -class ServerBuilderThreadCreatorOverrideTest; } // namespace testing /// A builder class for the creation and startup of \a grpc::Server instances. @@ -216,17 +213,6 @@ class ServerBuilder { private: friend class ::grpc::testing::ServerBuilderPluginTest; - friend class ::grpc::testing::ServerBuilderThreadCreatorOverrideTest; - - ServerBuilder& SetThreadFunctions( - std::function - thread_creator, - std::function thread_joiner) { - thread_creator_ = thread_creator; - thread_joiner_ = thread_joiner; - return *this; - } struct Port { grpc::string addr; @@ -286,11 +272,6 @@ class ServerBuilder { grpc_compression_algorithm algorithm; } maybe_default_compression_algorithm_; uint32_t enabled_compression_algorithms_bitset_; - - std::function - thread_creator_; - std::function thread_joiner_; }; } // namespace grpc diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index 94519d817b..4fb128d98b 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -189,16 +189,10 @@ int MetadataCredentialsPluginWrapper::GetMetadata( } if (w->plugin_->IsBlocking()) { // Asynchronous return. - if (w->thread_pool_->Add(std::bind( - &MetadataCredentialsPluginWrapper::InvokePlugin, w, context, cb, - user_data, nullptr, nullptr, nullptr, nullptr))) { - return 0; - } else { - *num_creds_md = 0; - *status = GRPC_STATUS_RESOURCE_EXHAUSTED; - *error_details = nullptr; - return true; - } + w->thread_pool_->Add( + std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context, + cb, user_data, nullptr, nullptr, nullptr, nullptr)); + return 0; } else { // Synchronous return. w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status, diff --git a/src/cpp/server/create_default_thread_pool.cc b/src/cpp/server/create_default_thread_pool.cc index 2d2abbe9d1..8ca3e32c2f 100644 --- a/src/cpp/server/create_default_thread_pool.cc +++ b/src/cpp/server/create_default_thread_pool.cc @@ -28,7 +28,7 @@ namespace { ThreadPoolInterface* CreateDefaultThreadPoolImpl() { int cores = gpr_cpu_num_cores(); if (!cores) cores = 4; - return new DynamicThreadPool(cores, gpr_thd_new, gpr_thd_join); + return new DynamicThreadPool(cores); } CreateThreadPoolFunc g_ctp_impl = CreateDefaultThreadPoolImpl; diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index d0e62313f6..81c78fe739 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -19,32 +19,19 @@ #include "src/cpp/server/dynamic_thread_pool.h" #include +#include #include -#include namespace grpc { -DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool, - bool* valid) - : pool_(pool) { - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - - std::lock_guard l(dt_mu_); - valid_ = *valid = pool->thread_creator_( - &thd_, "dynamic thread", - [](void* th) { - reinterpret_cast(th)->ThreadFunc(); - }, - this, &opt); -} - +DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool) + : pool_(pool), + thd_(new std::thread(&DynamicThreadPool::DynamicThread::ThreadFunc, + this)) {} DynamicThreadPool::DynamicThread::~DynamicThread() { - std::lock_guard l(dt_mu_); - if (valid_) { - pool_->thread_joiner_(thd_); - } + thd_->join(); + thd_.reset(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { @@ -86,26 +73,15 @@ void DynamicThreadPool::ThreadFunc() { } } -DynamicThreadPool::DynamicThreadPool( - int reserve_threads, - std::function - thread_creator, - std::function thread_joiner) +DynamicThreadPool::DynamicThreadPool(int reserve_threads) : shutdown_(false), reserve_threads_(reserve_threads), nthreads_(0), - threads_waiting_(0), - thread_creator_(thread_creator), - thread_joiner_(thread_joiner) { + threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { std::lock_guard lock(mu_); nthreads_++; - bool valid; - auto* th = new DynamicThread(this, &valid); - if (!valid) { - delete th; - } + new DynamicThread(this); } } @@ -125,7 +101,7 @@ DynamicThreadPool::~DynamicThreadPool() { ReapThreads(&dead_threads_); } -bool DynamicThreadPool::Add(const std::function& callback) { +void DynamicThreadPool::Add(const std::function& callback) { std::lock_guard lock(mu_); // Add works to the callbacks list callbacks_.push(callback); @@ -133,12 +109,7 @@ bool DynamicThreadPool::Add(const std::function& callback) { if (threads_waiting_ == 0) { // Kick off a new thread nthreads_++; - bool valid; - auto* th = new DynamicThread(this, &valid); - if (!valid) { - delete th; - return false; - } + new DynamicThread(this); } else { cv_.notify_one(); } @@ -146,7 +117,6 @@ bool DynamicThreadPool::Add(const std::function& callback) { if (!dead_threads_.empty()) { ReapThreads(&dead_threads_); } - return true; } } // namespace grpc diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 75d31cd908..9237c6e5ca 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -24,9 +24,9 @@ #include #include #include +#include #include -#include #include "src/cpp/server/thread_pool_interface.h" @@ -34,26 +34,20 @@ namespace grpc { class DynamicThreadPool final : public ThreadPoolInterface { public: - DynamicThreadPool(int reserve_threads, - std::function - thread_creator, - std::function thread_joiner); + explicit DynamicThreadPool(int reserve_threads); ~DynamicThreadPool(); - bool Add(const std::function& callback) override; + void Add(const std::function& callback) override; private: class DynamicThread { public: - DynamicThread(DynamicThreadPool* pool, bool* valid); + DynamicThread(DynamicThreadPool* pool); ~DynamicThread(); private: DynamicThreadPool* pool_; - std::mutex dt_mu_; - gpr_thd_id thd_; - bool valid_; + std::unique_ptr thd_; void ThreadFunc(); }; std::mutex mu_; @@ -65,10 +59,6 @@ class DynamicThreadPool final : public ThreadPoolInterface { int nthreads_; int threads_waiting_; std::list dead_threads_; - std::function - thread_creator_; - std::function thread_joiner_; void ThreadFunc(); static void ReapThreads(std::list* tlist); diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index fa08a6200f..0fbe4ccd18 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -43,14 +43,9 @@ void AuthMetadataProcessorAyncWrapper::Process( return; } if (w->processor_->IsBlocking()) { - bool added = w->thread_pool_->Add( + w->thread_pool_->Add( std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w, context, md, num_md, cb, user_data)); - if (!added) { - // no thread available, so fail with temporary resource unavailability - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAVAILABLE, nullptr); - return; - } } else { // invoke directly. w->InvokeProcessor(context, md, num_md, cb, user_data); diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index d91ee7f4e3..200e477822 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "src/cpp/server/thread_pool_interface.h" @@ -44,9 +43,7 @@ ServerBuilder::ServerBuilder() max_send_message_size_(-1), sync_server_settings_(SyncServerSettings()), resource_quota_(nullptr), - generic_service_(nullptr), - thread_creator_(gpr_thd_new), - thread_joiner_(gpr_thd_join) { + generic_service_(nullptr) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); for (auto it = g_plugin_factory_list->begin(); it != g_plugin_factory_list->end(); it++) { @@ -265,7 +262,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { std::unique_ptr server(new Server( max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, - sync_server_settings_.cq_timeout_msec, thread_creator_, thread_joiner_)); + sync_server_settings_.cq_timeout_msec)); if (has_sync_methods) { // This is a Sync server diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 02a663d660..4f8f4e06fc 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -36,7 +36,6 @@ #include #include #include -#include #include "src/core/ext/transport/inproc/inproc_transport.h" #include "src/core/lib/profiling/timers.h" @@ -196,10 +195,8 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { call_(mrd->call_, server, &cq_, server->max_receive_message_size()), ctx_(mrd->deadline_, &mrd->request_metadata_), has_request_payload_(mrd->has_request_payload_), - request_payload_(has_request_payload_ ? mrd->request_payload_ - : nullptr), - method_(mrd->method_), - server_(server) { + request_payload_(mrd->request_payload_), + method_(mrd->method_) { ctx_.set_call(mrd->call_); ctx_.cq_ = &cq_; GPR_ASSERT(mrd->in_flight_); @@ -213,13 +210,10 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { } } - void Run(std::shared_ptr global_callbacks, - bool resources) { + void Run(std::shared_ptr global_callbacks) { ctx_.BeginCompletionOp(&call_); global_callbacks->PreSynchronousRequest(&ctx_); - auto* handler = resources ? method_->handler() - : server_->resource_exhausted_handler_.get(); - handler->RunHandler(internal::MethodHandler::HandlerParameter( + method_->handler()->RunHandler(internal::MethodHandler::HandlerParameter( &call_, &ctx_, request_payload_)); global_callbacks->PostSynchronousRequest(&ctx_); request_payload_ = nullptr; @@ -241,7 +235,6 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { const bool has_request_payload_; grpc_byte_buffer* request_payload_; internal::RpcServiceMethod* const method_; - Server* server_; }; private: @@ -262,15 +255,11 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { // appropriate RPC handlers class Server::SyncRequestThreadManager : public ThreadManager { public: - SyncRequestThreadManager( - Server* server, CompletionQueue* server_cq, - std::shared_ptr global_callbacks, int min_pollers, - int max_pollers, int cq_timeout_msec, - std::function - thread_creator, - std::function thread_joiner) - : ThreadManager(min_pollers, max_pollers, thread_creator, thread_joiner), + SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, + std::shared_ptr global_callbacks, + int min_pollers, int max_pollers, + int cq_timeout_msec) + : ThreadManager(min_pollers, max_pollers), server_(server), server_cq_(server_cq), cq_timeout_msec_(cq_timeout_msec), @@ -296,7 +285,7 @@ class Server::SyncRequestThreadManager : public ThreadManager { GPR_UNREACHABLE_CODE(return TIMEOUT); } - void DoWork(void* tag, bool ok, bool resources) override { + void DoWork(void* tag, bool ok) override { SyncRequest* sync_req = static_cast(tag); if (!sync_req) { @@ -316,7 +305,7 @@ class Server::SyncRequestThreadManager : public ThreadManager { } GPR_TIMER_SCOPE("cd.Run()", 0); - cd.Run(global_callbacks_, resources); + cd.Run(global_callbacks_); } // TODO (sreek) If ok is false here (which it isn't in case of // grpc_request_registered_call), we should still re-queue the request @@ -378,11 +367,7 @@ Server::Server( int max_receive_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec, - std::function - thread_creator, - std::function thread_joiner) + int min_pollers, int max_pollers, int sync_cq_timeout_msec) : max_receive_message_size_(max_receive_message_size), sync_server_cqs_(sync_server_cqs), started_(false), @@ -391,9 +376,7 @@ Server::Server( has_generic_service_(false), server_(nullptr), server_initializer_(new ServerInitializer(this)), - health_check_service_disabled_(false), - thread_creator_(thread_creator), - thread_joiner_(thread_joiner) { + health_check_service_disabled_(false) { g_gli_initializer.summon(); gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); global_callbacks_ = g_callbacks; @@ -403,7 +386,7 @@ Server::Server( it++) { sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( this, (*it).get(), global_callbacks_, min_pollers, max_pollers, - sync_cq_timeout_msec, thread_creator_, thread_joiner_)); + sync_cq_timeout_msec)); } grpc_channel_args channel_args; @@ -566,10 +549,6 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { } } - if (!sync_server_cqs_->empty()) { - resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler); - } - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Start(); } diff --git a/src/cpp/server/thread_pool_interface.h b/src/cpp/server/thread_pool_interface.h index 656e6673f1..028842a776 100644 --- a/src/cpp/server/thread_pool_interface.h +++ b/src/cpp/server/thread_pool_interface.h @@ -29,9 +29,7 @@ class ThreadPoolInterface { virtual ~ThreadPoolInterface() {} // Schedule the given callback for execution. - // Return true on success, false on failure - virtual bool Add(const std::function& callback) - GRPC_MUST_USE_RESULT = 0; + virtual void Add(const std::function& callback) = 0; }; // Allows different codebases to use their own thread pool impls diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 107c60f4eb..23264f1b5b 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -20,26 +20,18 @@ #include #include +#include #include -#include namespace grpc { -ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr, bool* valid) +ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr) : thd_mgr_(thd_mgr) { - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - // Make thread creation exclusive with respect to its join happening in // ~WorkerThread(). std::lock_guard lock(wt_mu_); - *valid = valid_ = thd_mgr->thread_creator_( - &thd_, "worker thread", - [](void* th) { - reinterpret_cast(th)->Run(); - }, - this, &opt); + thd_ = std::thread(&ThreadManager::WorkerThread::Run, this); } void ThreadManager::WorkerThread::Run() { @@ -50,24 +42,15 @@ void ThreadManager::WorkerThread::Run() { ThreadManager::WorkerThread::~WorkerThread() { // Don't join until the thread is fully constructed. std::lock_guard lock(wt_mu_); - if (valid_) { - thd_mgr_->thread_joiner_(thd_); - } + thd_.join(); } -ThreadManager::ThreadManager( - int min_pollers, int max_pollers, - std::function - thread_creator, - std::function thread_joiner) +ThreadManager::ThreadManager(int min_pollers, int max_pollers) : shutdown_(false), num_pollers_(0), min_pollers_(min_pollers), max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers), - num_threads_(0), - thread_creator_(thread_creator), - thread_joiner_(thread_joiner) {} + num_threads_(0) {} ThreadManager::~ThreadManager() { { @@ -128,9 +111,7 @@ void ThreadManager::Initialize() { for (int i = 0; i < min_pollers_; i++) { // Create a new thread (which ends up calling the MainWorkLoop() function - bool valid; - new WorkerThread(this, &valid); - GPR_ASSERT(valid); // we need to have at least this minimum + new WorkerThread(this); } } @@ -157,27 +138,18 @@ void ThreadManager::MainWorkLoop() { case WORK_FOUND: // If we got work and there are now insufficient pollers, start a new // one - bool resources; if (!shutdown_ && num_pollers_ < min_pollers_) { - bool valid; + num_pollers_++; + num_threads_++; // Drop lock before spawning thread to avoid contention lock.unlock(); - auto* th = new WorkerThread(this, &valid); - lock.lock(); - if (valid) { - num_pollers_++; - num_threads_++; - } else { - delete th; - } - resources = (num_pollers_ > 0); + new WorkerThread(this); } else { - resources = true; + // Drop lock for consistency with above branch + lock.unlock(); } - // Drop lock before any application work - lock.unlock(); // Lock is always released at this point - do the application work - DoWork(tag, ok, resources); + DoWork(tag, ok); // Take the lock again to check post conditions lock.lock(); // If we're shutdown, we should finish at this point. diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index c1783baa60..a206e0bd8a 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -20,23 +20,18 @@ #define GRPC_INTERNAL_CPP_THREAD_MANAGER_H #include -#include #include #include #include +#include #include -#include namespace grpc { class ThreadManager { public: - ThreadManager(int min_pollers, int max_pollers, - std::function - thread_creator, - std::function thread_joiner); + explicit ThreadManager(int min_pollers, int max_pollers); virtual ~ThreadManager(); // Initializes and Starts the Rpc Manager threads @@ -55,8 +50,6 @@ class ThreadManager { // - ThreadManager does not interpret the values of 'tag' and 'ok' // - ThreadManager WILL call DoWork() and pass '*tag' and 'ok' as input to // DoWork() - // - ThreadManager will also pass DoWork a bool saying if there are actually - // resources to do the work // // If the return value is SHUTDOWN:, // - ThreadManager WILL NOT call DoWork() and terminates the thead @@ -76,7 +69,7 @@ class ThreadManager { // The implementation of DoWork() should also do any setup needed to ensure // that the next call to PollForWork() (not necessarily by the current thread) // actually finds some work - virtual void DoWork(void* tag, bool ok, bool resources) = 0; + virtual void DoWork(void* tag, bool ok) = 0; // Mark the ThreadManager as shutdown and begin draining the work. This is a // non-blocking call and the caller should call Wait(), a blocking call which @@ -91,15 +84,15 @@ class ThreadManager { virtual void Wait(); private: - // Helper wrapper class around thread. This takes a ThreadManager object - // and starts a new thread to calls the Run() function. + // Helper wrapper class around std::thread. This takes a ThreadManager object + // and starts a new std::thread to calls the Run() function. // // The Run() function calls ThreadManager::MainWorkLoop() function and once // that completes, it marks the WorkerThread completed by calling // ThreadManager::MarkAsCompleted() class WorkerThread { public: - WorkerThread(ThreadManager* thd_mgr, bool* valid); + WorkerThread(ThreadManager* thd_mgr); ~WorkerThread(); private: @@ -109,8 +102,7 @@ class ThreadManager { ThreadManager* const thd_mgr_; std::mutex wt_mu_; - gpr_thd_id thd_; - bool valid_; + std::thread thd_; }; // The main funtion in ThreadManager @@ -137,13 +129,6 @@ class ThreadManager { // currently polling i.e num_pollers_) int num_threads_; - // Functions for creating/joining threads. Normally, these should - // be gpr_thd_new/gpr_thd_join but they are overridable - std::function - thread_creator_; - std::function thread_joiner_; - std::mutex list_mu_; std::list completed_threads_; }; diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index fd43c8f584..90b2eddbbb 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -53,13 +52,63 @@ namespace testing { class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { public: - TestServiceImpl() {} + TestServiceImpl() : signal_client_(false) {} Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { response->set_message(request->message()); return Status::OK; } + + // Unimplemented is left unimplemented to test the returned error. + + Status RequestStream(ServerContext* context, + ServerReader* reader, + EchoResponse* response) override { + EchoRequest request; + response->set_message(""); + while (reader->Read(&request)) { + response->mutable_message()->append(request.message()); + } + return Status::OK; + } + + // Return 3 messages. + // TODO(yangg) make it generic by adding a parameter into EchoRequest + Status ResponseStream(ServerContext* context, const EchoRequest* request, + ServerWriter* writer) override { + EchoResponse response; + response.set_message(request->message() + "0"); + writer->Write(response); + response.set_message(request->message() + "1"); + writer->Write(response); + response.set_message(request->message() + "2"); + writer->Write(response); + + return Status::OK; + } + + Status BidiStream( + ServerContext* context, + ServerReaderWriter* stream) override { + EchoRequest request; + EchoResponse response; + while (stream->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + response.set_message(request.message()); + stream->Write(response); + } + return Status::OK; + } + + bool signal_client() { + std::unique_lock lock(mu_); + return signal_client_; + } + + private: + bool signal_client_; + std::mutex mu_; }; template @@ -70,15 +119,10 @@ class CommonStressTest { virtual void SetUp() = 0; virtual void TearDown() = 0; virtual void ResetStub() = 0; - virtual bool AllowExhaustion() = 0; grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); } protected: std::unique_ptr stub_; - // Some tests use a custom thread creator. This should be declared before the - // server so that it's destructor happens after the server - std::unique_ptr creator_; - std::unique_ptr server_; virtual void SetUpStart(ServerBuilder* builder, Service* service) = 0; @@ -103,7 +147,6 @@ class CommonStressTestInsecure : public CommonStressTest { CreateChannel(server_address_.str(), InsecureChannelCredentials()); this->stub_ = grpc::testing::EchoTestService::NewStub(channel); } - bool AllowExhaustion() override { return false; } protected: void SetUpStart(ServerBuilder* builder, Service* service) override { @@ -119,7 +162,7 @@ class CommonStressTestInsecure : public CommonStressTest { std::ostringstream server_address_; }; -template +template class CommonStressTestInproc : public CommonStressTest { public: void ResetStub() override { @@ -127,7 +170,6 @@ class CommonStressTestInproc : public CommonStressTest { std::shared_ptr channel = this->server_->InProcessChannel(args); this->stub_ = grpc::testing::EchoTestService::NewStub(channel); } - bool AllowExhaustion() override { return allow_resource_exhaustion; } protected: void SetUpStart(ServerBuilder* builder, Service* service) override { @@ -152,67 +194,6 @@ class CommonStressTestSyncServer : public BaseClass { TestServiceImpl service_; }; -class ServerBuilderThreadCreatorOverrideTest { - public: - ServerBuilderThreadCreatorOverrideTest(ServerBuilder* builder, size_t limit) - : limit_(limit), threads_(0) { - builder->SetThreadFunctions( - [this](gpr_thd_id* id, const char* name, void (*f)(void*), void* arg, - const gpr_thd_options* options) -> int { - std::unique_lock l(mu_); - if (threads_ < limit_) { - l.unlock(); - if (gpr_thd_new(id, name, f, arg, options) != 0) { - l.lock(); - threads_++; - return 1; - } - } - return 0; - }, - [this](gpr_thd_id id) { - gpr_thd_join(id); - std::unique_lock l(mu_); - threads_--; - if (threads_ == 0) { - done_.notify_one(); - } - }); - } - ~ServerBuilderThreadCreatorOverrideTest() { - // Don't allow destruction until all threads are really done and uncounted - std::unique_lock l(mu_); - done_.wait(l, [this] { return (threads_ == 0); }); - } - - private: - size_t limit_; - size_t threads_; - std::mutex mu_; - std::condition_variable done_; -}; - -template -class CommonStressTestSyncServerLowThreadCount : public BaseClass { - public: - void SetUp() override { - ServerBuilder builder; - this->SetUpStart(&builder, &service_); - builder.SetSyncServerOption(ServerBuilder::SyncServerOption::MIN_POLLERS, - 1); - this->creator_.reset( - new ServerBuilderThreadCreatorOverrideTest(&builder, 4)); - this->SetUpEnd(&builder); - } - void TearDown() override { - this->TearDownStart(); - this->TearDownEnd(); - } - - private: - TestServiceImpl service_; -}; - template class CommonStressTestAsyncServer : public BaseClass { public: @@ -313,8 +294,7 @@ class End2endTest : public ::testing::Test { Common common_; }; -static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, - bool allow_exhaustion, gpr_atm* errors) { +static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs) { EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -322,48 +302,33 @@ static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, for (int i = 0; i < num_rpcs; ++i) { ClientContext context; Status s = stub->Echo(&context, request, &response); - EXPECT_TRUE(s.ok() || (allow_exhaustion && - s.error_code() == StatusCode::RESOURCE_EXHAUSTED)); + EXPECT_EQ(response.message(), request.message()); if (!s.ok()) { - if (!(allow_exhaustion && - s.error_code() == StatusCode::RESOURCE_EXHAUSTED)) { - gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), - s.error_message().c_str()); - } - gpr_atm_no_barrier_fetch_add(errors, static_cast(1)); - } else { - EXPECT_EQ(response.message(), request.message()); + gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), + s.error_message().c_str()); } + ASSERT_TRUE(s.ok()); } } typedef ::testing::Types< CommonStressTestSyncServer>, - CommonStressTestSyncServer>, - CommonStressTestSyncServerLowThreadCount< - CommonStressTestInproc>, + CommonStressTestSyncServer>, CommonStressTestAsyncServer< CommonStressTestInsecure>, - CommonStressTestAsyncServer>> + CommonStressTestAsyncServer< + CommonStressTestInproc>> CommonTypes; TYPED_TEST_CASE(End2endTest, CommonTypes); TYPED_TEST(End2endTest, ThreadStress) { this->common_.ResetStub(); std::vector threads; - gpr_atm errors; - gpr_atm_rel_store(&errors, static_cast(0)); for (int i = 0; i < kNumThreads; ++i) { - threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs, - this->common_.AllowExhaustion(), &errors); + threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs); } for (int i = 0; i < kNumThreads; ++i) { threads[i].join(); } - uint64_t error_cnt = static_cast(gpr_atm_no_barrier_load(&errors)); - if (error_cnt != 0) { - gpr_log(GPR_INFO, "RPC error count: %" PRIu64, error_cnt); - } } template diff --git a/test/cpp/thread_manager/BUILD b/test/cpp/thread_manager/BUILD deleted file mode 100644 index 1f0878770b..0000000000 --- a/test/cpp/thread_manager/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2017 gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -licenses(["notice"]) # Apache v2 - -load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") - -grpc_package(name = "test/cpp/thread_manager") - -grpc_cc_test( - name = "thread_manager_test", - srcs = ["thread_manager_test.cc"], - deps = [ - "//:gpr", - "//:grpc", - "//:grpc++", - "//test/cpp/util:test_config", - ], -) - diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index d3d31f9dd9..8282d46694 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -20,10 +20,10 @@ #include #include +#include #include #include #include -#include #include "src/cpp/thread_manager/thread_manager.h" #include "test/cpp/util/test_config.h" @@ -32,13 +32,13 @@ namespace grpc { class ThreadManagerTest final : public grpc::ThreadManager { public: ThreadManagerTest() - : ThreadManager(kMinPollers, kMaxPollers, gpr_thd_new, gpr_thd_join), + : ThreadManager(kMinPollers, kMaxPollers), num_do_work_(0), num_poll_for_work_(0), num_work_found_(0) {} grpc::ThreadManager::WorkStatus PollForWork(void** tag, bool* ok) override; - void DoWork(void* tag, bool ok, bool resources) override; + void DoWork(void* tag, bool ok) override; void PerformTest(); private: @@ -89,7 +89,7 @@ grpc::ThreadManager::WorkStatus ThreadManagerTest::PollForWork(void** tag, } } -void ThreadManagerTest::DoWork(void* tag, bool ok, bool resources) { +void ThreadManagerTest::DoWork(void* tag, bool ok) { gpr_atm_no_barrier_fetch_add(&num_do_work_, 1); SleepForMs(kDoWorkDurationMsec); // Simulate doing work by sleeping } -- cgit v1.2.3 From 86c17bfc7d5a191e3738038028c1cfd7b3c181cf Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 12 Jan 2018 13:55:51 +0100 Subject: start with fewer iterations --- test/core/support/sync_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/core/support/sync_test.cc b/test/core/support/sync_test.cc index 04b9e94cbc..768f96d093 100644 --- a/test/core/support/sync_test.cc +++ b/test/core/support/sync_test.cc @@ -231,7 +231,7 @@ static void mark_thread_done(struct test* m) { */ static void test(const char* name, void (*body)(void* m), void (*extra)(void* m), int timeout_s, int incr_step) { - int64_t iterations = 1024; + int64_t iterations = 256; struct test* m; gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec time_taken; @@ -240,7 +240,6 @@ static void test(const char* name, void (*body)(void* m), fprintf(stderr, "%s:", name); fflush(stderr); while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { - iterations <<= 1; fprintf(stderr, " %ld", (long)iterations); fflush(stderr); m = test_new(10, iterations, incr_step); @@ -258,6 +257,7 @@ static void test(const char* name, void (*body)(void* m), GPR_ASSERT(0); } test_destroy(m); + iterations <<= 1; } time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, -- cgit v1.2.3 From 94dad609783b0e67c9b4b1de079330e19cf813c2 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Jan 2018 12:29:09 -0800 Subject: Add equality operators to RefCountedPtr. --- src/core/lib/support/ref_counted_ptr.h | 13 +++++++++++++ test/core/support/ref_counted_ptr_test.cc | 13 +++++++++++++ 2 files changed, 26 insertions(+) (limited to 'test') diff --git a/src/core/lib/support/ref_counted_ptr.h b/src/core/lib/support/ref_counted_ptr.h index dc2385e369..83e99d8ca6 100644 --- a/src/core/lib/support/ref_counted_ptr.h +++ b/src/core/lib/support/ref_counted_ptr.h @@ -76,6 +76,19 @@ class RefCountedPtr { T& operator*() const { return *value_; } T* operator->() const { return value_; } + bool operator==(const RefCountedPtr& other) const { + return value_ == other.value_; + } + bool operator==(T* other) const { + return value_ == other; + } + bool operator!=(const RefCountedPtr& other) const { + return value_ != other.value_; + } + bool operator!=(T* other) const { + return value_ != other; + } + private: T* value_ = nullptr; }; diff --git a/test/core/support/ref_counted_ptr_test.cc b/test/core/support/ref_counted_ptr_test.cc index 1830edc4e5..ce4975d347 100644 --- a/test/core/support/ref_counted_ptr_test.cc +++ b/test/core/support/ref_counted_ptr_test.cc @@ -138,6 +138,19 @@ TEST(RefCountedPtr, DerefernceOperators) { foo_ref.value(); } +TEST(RefCountedPtr, EqualityOperators) { + RefCountedPtr foo(New()); + RefCountedPtr bar = foo; + RefCountedPtr empty; + // Test equality between RefCountedPtrs. + EXPECT_EQ(foo, bar); + EXPECT_NE(foo, empty); + // Test equality with bare pointers. + EXPECT_EQ(foo, foo.get()); + EXPECT_EQ(empty, nullptr); + EXPECT_NE(foo, nullptr); +} + TEST(MakeRefCounted, NoArgs) { RefCountedPtr foo = MakeRefCounted(); EXPECT_EQ(0, foo->value()); -- cgit v1.2.3 From be448700590c5995dd2bdf95223aa5de96d02160 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 16 Jan 2018 12:49:18 -0800 Subject: Fix issue whereby fuzzer creates infinitely deep creds (since this is not actually interesting) --- test/core/end2end/fuzzers/api_fuzzer.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc index 967a6d560f..884cbdb3e5 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -280,7 +280,11 @@ static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) { return creds; } -static grpc_call_credentials* read_call_creds(input_stream* inp) { +static grpc_call_credentials* read_call_creds(input_stream* inp, int depth) { + if (depth > 64) { + // prevent creating infinitely deep call creds + return nullptr; + } switch (next_byte(inp)) { default: end(inp); @@ -288,8 +292,8 @@ static grpc_call_credentials* read_call_creds(input_stream* inp) { case 0: return nullptr; case 1: { - grpc_call_credentials* c1 = read_call_creds(inp); - grpc_call_credentials* c2 = read_call_creds(inp); + grpc_call_credentials* c1 = read_call_creds(inp, depth + 1); + grpc_call_credentials* c2 = read_call_creds(inp, depth + 1); if (c1 != nullptr && c2 != nullptr) { grpc_call_credentials* out = grpc_composite_call_credentials_create(c1, c2, nullptr); @@ -338,7 +342,7 @@ static grpc_channel_credentials* read_channel_creds(input_stream* inp) { break; case 1: { grpc_channel_credentials* c1 = read_channel_creds(inp); - grpc_call_credentials* c2 = read_call_creds(inp); + grpc_call_credentials* c2 = read_call_creds(inp, 0); if (c1 != nullptr && c2 != nullptr) { grpc_channel_credentials* out = grpc_composite_channel_credentials_create(c1, c2, nullptr); -- cgit v1.2.3 From d7ae4a1c617f319f6c8f31890bdacadc343037b7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 16 Jan 2018 12:51:33 -0800 Subject: Also stop processing input stream --- test/core/end2end/fuzzers/api_fuzzer.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc index 884cbdb3e5..43c9fa19c6 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -283,6 +283,7 @@ static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) { static grpc_call_credentials* read_call_creds(input_stream* inp, int depth) { if (depth > 64) { // prevent creating infinitely deep call creds + end(inp); return nullptr; } switch (next_byte(inp)) { -- cgit v1.2.3 From 33cb50096ce04612479e8a64626e5ddc200c6db1 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 16 Jan 2018 13:16:21 -0800 Subject: Add fuzzed example that found this crash --- .../fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5 | Bin 0 -> 48866 bytes tools/run_tests/generated/tests.json | 23 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5 (limited to 'test') diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5 new file mode 100644 index 0000000000..1745798b68 Binary files /dev/null and b/test/core/end2end/fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5 differ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index afeee0b323..6f36dff820 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -105417,6 +105417,29 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/fuzz-input-d2ab5" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "mac", + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/poc-c726ee220e980ed6ad17809fd9efe2844ee61555ac08e4f88afd8901cc2dd53a" -- cgit v1.2.3