diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e7917ae6af..3c424397c1 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - version = '1.65.4' + version = '1.65.5' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f2b8814eac..3016c0ba57 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.65.4' + version = '1.65.5' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 4150746fb3..f0883115f3 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.65.4' + version = '1.65.5' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 11335c489f..3a5d75236e 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.65.4' + version = '1.65.5' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index c3e89f768a..52d434a8d0 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.65.4' + version = '1.65.5' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/include/grpcpp/version_info.h b/include/grpcpp/version_info.h index 6f4d451b74..a65e3fd4e2 100644 --- a/include/grpcpp/version_info.h +++ b/include/grpcpp/version_info.h @@ -20,8 +20,8 @@ #define GRPC_CPP_VERSION_MAJOR 1 #define GRPC_CPP_VERSION_MINOR 65 -#define GRPC_CPP_VERSION_PATCH 4 +#define GRPC_CPP_VERSION_PATCH 5 #define GRPC_CPP_VERSION_TAG "" -#define GRPC_CPP_VERSION_STRING "1.65.4" +#define GRPC_CPP_VERSION_STRING "1.65.5" #endif // GRPCPP_VERSION_INFO_H diff --git a/src/core/handshaker/security/secure_endpoint.cc b/src/core/handshaker/security/secure_endpoint.cc index 18fde15243..fb942cff95 100644 --- a/src/core/handshaker/security/secure_endpoint.cc +++ b/src/core/handshaker/security/secure_endpoint.cc @@ -105,7 +105,6 @@ struct secure_endpoint { } ~secure_endpoint() { - memory_owner.Reset(); tsi_frame_protector_destroy(protector); tsi_zero_copy_grpc_protector_destroy(zero_copy_protector); grpc_slice_buffer_destroy(&source_buffer); @@ -255,6 +254,13 @@ static void on_read(void* user_data, grpc_error_handle error) { { grpc_core::MutexLock l(&ep->read_mu); + + // If we were shut down after this callback was scheduled with OK + // status but before it was invoked, we need to treat that as an error. + if (ep->wrapped_ep == nullptr && error.ok()) { + error = absl::CancelledError("secure endpoint shutdown"); + } + uint8_t* cur = GRPC_SLICE_START_PTR(ep->read_staging_buffer); uint8_t* end = GRPC_SLICE_END_PTR(ep->read_staging_buffer); @@ -382,9 +388,12 @@ static void flush_write_staging_buffer(secure_endpoint* ep, uint8_t** cur, static void on_write(void* user_data, grpc_error_handle error) { secure_endpoint* ep = static_cast(user_data); - grpc_core::ExecCtx::Run(DEBUG_LOCATION, std::exchange(ep->write_cb, nullptr), - std::move(error)); + grpc_closure* cb = ep->write_cb; + ep->write_cb = nullptr; SECURE_ENDPOINT_UNREF(ep, "write"); + grpc_core::EnsureRunInExecCtx([cb, error = std::move(error)]() { + grpc_core::Closure::Run(DEBUG_LOCATION, cb, error); + }); } static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, @@ -506,7 +515,10 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, static void endpoint_destroy(grpc_endpoint* secure_ep) { secure_endpoint* ep = reinterpret_cast(secure_ep); + ep->read_mu.Lock(); grpc_endpoint_destroy(ep->wrapped_ep); + ep->memory_owner.Reset(); + ep->read_mu.Unlock(); SECURE_ENDPOINT_UNREF(ep, "destroy"); } diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 2d4129c129..748f111a0b 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -493,6 +493,13 @@ void grpc_call_tracer_set(grpc_call* call, return arena->SetContext(tracer); } +void grpc_call_tracer_set_and_manage(grpc_call* call, + grpc_core::ClientCallTracer* tracer) { + grpc_core::Arena* arena = grpc_call_get_arena(call); + arena->ManagedNew(tracer); + return arena->SetContext(tracer); +} + void* grpc_call_tracer_get(grpc_call* call) { grpc_core::Arena* arena = grpc_call_get_arena(call); auto* call_tracer = diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 37805d8c91..ad4388e43b 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -274,6 +274,16 @@ void grpc_call_log_batch(const char* file, int line, gpr_log_severity severity, void grpc_call_tracer_set(grpc_call* call, grpc_core::ClientCallTracer* tracer); +// Sets call tracer on the call and manages its life by using the call's arena. +// When using this API, the tracer will be destroyed by grpc_call arena when +// grpc_call is about to be destroyed. The caller of this API SHOULD NOT +// manually destroy the tracer. This API is used by Python as a way of using +// Arena to manage the lifetime of the call tracer. Python needs this API +// because the tracer was created within a separate shared object library which +// doesn't have access to core functions like arena->ManagedNew<>. +void grpc_call_tracer_set_and_manage(grpc_call* call, + grpc_core::ClientCallTracer* tracer); + void* grpc_call_tracer_get(grpc_call* call); #define GRPC_CALL_LOG_BATCH(sev, ops, nops) \ @@ -285,6 +295,15 @@ void* grpc_call_tracer_get(grpc_call* call); uint8_t grpc_call_is_client(grpc_call* call); +class ClientCallTracerWrapper { + public: + explicit ClientCallTracerWrapper(grpc_core::ClientCallTracer* tracer) + : tracer_(tracer) {} + + private: + std::unique_ptr tracer_; +}; + // Return an appropriate compression algorithm for the requested compression \a // level in the context of \a call. grpc_compression_algorithm grpc_call_compression_for_level( diff --git a/src/core/load_balancing/rls/rls.cc b/src/core/load_balancing/rls/rls.cc index d2f76a6db0..af63f4615a 100644 --- a/src/core/load_balancing/rls/rls.cc +++ b/src/core/load_balancing/rls/rls.cc @@ -352,7 +352,8 @@ class RlsLb final : public LoadBalancingPolicy { // is called after releasing it. // // Both methods grab the data they need from the parent object. - void StartUpdate() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); + void StartUpdate(OrphanablePtr* child_policy_to_delete) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); absl::Status MaybeFinishUpdate() ABSL_LOCKS_EXCLUDED(&RlsLb::mu_); void ExitIdleLocked() { @@ -396,14 +397,14 @@ class RlsLb final : public LoadBalancingPolicy { }; // Note: We are forced to disable lock analysis here because - // Orphan() is called by Unref() which is called by RefCountedPtr<>, which + // Orphaned() is called by Unref() which is called by RefCountedPtr<>, which // cannot have lock annotations for this particular caller. void Orphaned() override ABSL_NO_THREAD_SAFETY_ANALYSIS; RefCountedPtr lb_policy_; std::string target_; - bool is_shutdown_ = false; + bool is_shutdown_ = false; // Protected by WorkSerializer OrphanablePtr child_policy_; RefCountedPtr pending_config_; @@ -502,12 +503,25 @@ class RlsLb final : public LoadBalancingPolicy { // Returns a list of child policy wrappers on which FinishUpdate() // needs to be called after releasing the lock. std::vector OnRlsResponseLocked( - ResponseInfo response, std::unique_ptr backoff_state) + ResponseInfo response, std::unique_ptr backoff_state, + OrphanablePtr* child_policy_to_delete) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); // Moves entry to the end of the LRU list. void MarkUsed() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); + // Takes entries from child_policy_wrappers_ and appends them to the end + // of \a child_policy_wrappers. + void TakeChildPolicyWrappers( + std::vector>* child_policy_wrappers) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_) { + child_policy_wrappers->insert( + child_policy_wrappers->end(), + std::make_move_iterator(child_policy_wrappers_.begin()), + std::make_move_iterator(child_policy_wrappers_.end())); + child_policy_wrappers_.clear(); + } + private: class BackoffTimer final : public InternallyRefCounted { public: @@ -564,19 +578,24 @@ class RlsLb final : public LoadBalancingPolicy { // the caller. Otherwise, the entry found is returned to the caller. The // entry returned to the user is considered recently used and its order in // the LRU list of the cache is updated. - Entry* FindOrInsert(const RequestKey& key) + Entry* FindOrInsert(const RequestKey& key, + std::vector>* + child_policy_wrappers_to_delete) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); // Resizes the cache. If the new cache size is greater than the current size // of the cache, do nothing. Otherwise, evict the oldest entries that // exceed the new size limit of the cache. - void Resize(size_t bytes) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); + void Resize(size_t bytes, std::vector>* + child_policy_wrappers_to_delete) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); // Resets backoff of all the cache entries. void ResetAllBackoff() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); // Shutdown the cache; clean-up and orphan all the stored cache entries. - void Shutdown() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); + GRPC_MUST_USE_RESULT std::vector> + Shutdown() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); void ReportMetricsLocked(CallbackMetricReporter& reporter) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); @@ -592,7 +611,9 @@ class RlsLb final : public LoadBalancingPolicy { // Evicts oversized cache elements when the current size is greater than // the specified limit. - void MaybeShrinkSize(size_t bytes) + void MaybeShrinkSize(size_t bytes, + std::vector>* + child_policy_wrappers_to_delete) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); RlsLb* lb_policy_; @@ -856,7 +877,8 @@ absl::optional InsertOrUpdateChildPolicyField(const std::string& field, return Json::FromArray(std::move(array)); } -void RlsLb::ChildPolicyWrapper::StartUpdate() { +void RlsLb::ChildPolicyWrapper::StartUpdate( + OrphanablePtr* child_policy_to_delete) { ValidationErrors errors; auto child_policy_config = InsertOrUpdateChildPolicyField( lb_policy_->config_->child_policy_config_target_field_name(), target_, @@ -884,7 +906,7 @@ void RlsLb::ChildPolicyWrapper::StartUpdate() { pending_config_.reset(); picker_ = MakeRefCounted( absl::UnavailableError(config.status().message())); - child_policy_.reset(); + *child_policy_to_delete = std::move(child_policy_); } else { pending_config_ = std::move(*config); } @@ -941,9 +963,9 @@ void RlsLb::ChildPolicyWrapper::ChildPolicyHelper::UpdateState( wrapper_->target_.c_str(), this, ConnectivityStateName(state), status.ToString().c_str(), picker.get()); } + if (wrapper_->is_shutdown_) return; { MutexLock lock(&wrapper_->lb_policy_->mu_); - if (wrapper_->is_shutdown_) return; // TODO(roth): It looks like this ignores subsequent TF updates that // might change the status used to fail picks, which seems wrong. if (wrapper_->connectivity_state_ == GRPC_CHANNEL_TRANSIENT_FAILURE && @@ -953,7 +975,8 @@ void RlsLb::ChildPolicyWrapper::ChildPolicyHelper::UpdateState( wrapper_->connectivity_state_ = state; DCHECK(picker != nullptr); if (picker != nullptr) { - wrapper_->picker_ = std::move(picker); + // We want to unref the picker after we release the lock. + wrapper_->picker_.swap(picker); } } wrapper_->lb_policy_->UpdatePickerLocked(); @@ -1204,19 +1227,19 @@ RlsLb::Cache::Entry::Entry(RefCountedPtr lb_policy, lb_policy_->cache_.lru_list_.end(), key)) {} void RlsLb::Cache::Entry::Orphan() { - if (GRPC_TRACE_FLAG_ENABLED(rls_lb)) { - gpr_log(GPR_INFO, "[rlslb %p] cache entry=%p %s: cache entry evicted", - lb_policy_.get(), this, lru_iterator_->ToString().c_str()); - } + // We should be holding RlsLB::mu_. + GRPC_TRACE_LOG(rls_lb, INFO) + << "[rlslb " << lb_policy_.get() << "] cache entry=" << this << " " + << lru_iterator_->ToString() << ": cache entry evicted"; is_shutdown_ = true; lb_policy_->cache_.lru_list_.erase(lru_iterator_); lru_iterator_ = lb_policy_->cache_.lru_list_.end(); // Just in case. + CHECK(child_policy_wrappers_.empty()); backoff_state_.reset(); if (backoff_timer_ != nullptr) { backoff_timer_.reset(); lb_policy_->UpdatePickerAsync(); } - child_policy_wrappers_.clear(); Unref(DEBUG_LOCATION, "Orphan"); } @@ -1298,7 +1321,8 @@ void RlsLb::Cache::Entry::MarkUsed() { std::vector RlsLb::Cache::Entry::OnRlsResponseLocked( - ResponseInfo response, std::unique_ptr backoff_state) { + ResponseInfo response, std::unique_ptr backoff_state, + OrphanablePtr* child_policy_to_delete) { // Move the entry to the end of the LRU list. MarkUsed(); // If the request failed, store the failed status and update the @@ -1359,7 +1383,7 @@ RlsLb::Cache::Entry::OnRlsResponseLocked( if (it == lb_policy_->child_policy_map_.end()) { auto new_child = MakeRefCounted( lb_policy_.Ref(DEBUG_LOCATION, "ChildPolicyWrapper"), target); - new_child->StartUpdate(); + new_child->StartUpdate(child_policy_to_delete); child_policies_to_finish_update.push_back(new_child.get()); new_child_policy_wrappers.emplace_back(std::move(new_child)); } else { @@ -1396,12 +1420,15 @@ RlsLb::Cache::Entry* RlsLb::Cache::Find(const RequestKey& key) { return it->second.get(); } -RlsLb::Cache::Entry* RlsLb::Cache::FindOrInsert(const RequestKey& key) { +RlsLb::Cache::Entry* RlsLb::Cache::FindOrInsert( + const RequestKey& key, std::vector>* + child_policy_wrappers_to_delete) { auto it = map_.find(key); // If not found, create new entry. if (it == map_.end()) { size_t entry_size = EntrySizeForKey(key); - MaybeShrinkSize(size_limit_ - std::min(size_limit_, entry_size)); + MaybeShrinkSize(size_limit_ - std::min(size_limit_, entry_size), + child_policy_wrappers_to_delete); Entry* entry = new Entry( lb_policy_->RefAsSubclass(DEBUG_LOCATION, "CacheEntry"), key); map_.emplace(key, OrphanablePtr(entry)); @@ -1421,13 +1448,13 @@ RlsLb::Cache::Entry* RlsLb::Cache::FindOrInsert(const RequestKey& key) { return it->second.get(); } -void RlsLb::Cache::Resize(size_t bytes) { - if (GRPC_TRACE_FLAG_ENABLED(rls_lb)) { - gpr_log(GPR_INFO, "[rlslb %p] resizing cache to %" PRIuPTR " bytes", - lb_policy_, bytes); - } +void RlsLb::Cache::Resize(size_t bytes, + std::vector>* + child_policy_wrappers_to_delete) { + GRPC_TRACE_LOG(rls_lb, INFO) + << "[rlslb " << lb_policy_ << "] resizing cache to " << bytes << " bytes"; size_limit_ = bytes; - MaybeShrinkSize(size_limit_); + MaybeShrinkSize(size_limit_, child_policy_wrappers_to_delete); } void RlsLb::Cache::ResetAllBackoff() { @@ -1437,7 +1464,12 @@ void RlsLb::Cache::ResetAllBackoff() { lb_policy_->UpdatePickerAsync(); } -void RlsLb::Cache::Shutdown() { +std::vector> RlsLb::Cache::Shutdown() { + std::vector> + child_policy_wrappers_to_delete; + for (auto& entry : map_) { + entry.second->TakeChildPolicyWrappers(&child_policy_wrappers_to_delete); + } map_.clear(); lru_list_.clear(); if (cleanup_timer_handle_.has_value() && @@ -1448,6 +1480,7 @@ void RlsLb::Cache::Shutdown() { } } cleanup_timer_handle_.reset(); + return child_policy_wrappers_to_delete; } void RlsLb::Cache::ReportMetricsLocked(CallbackMetricReporter& reporter) { @@ -1481,15 +1514,17 @@ void RlsLb::Cache::StartCleanupTimer() { } void RlsLb::Cache::OnCleanupTimer() { - if (GRPC_TRACE_FLAG_ENABLED(rls_lb)) { - gpr_log(GPR_INFO, "[rlslb %p] cache cleanup timer fired", lb_policy_); - } + GRPC_TRACE_LOG(rls_lb, INFO) + << "[rlslb " << lb_policy_ << "] cache cleanup timer fired"; + std::vector> + child_policy_wrappers_to_delete; MutexLock lock(&lb_policy_->mu_); if (!cleanup_timer_handle_.has_value()) return; if (lb_policy_->is_shutdown_) return; for (auto it = map_.begin(); it != map_.end();) { if (GPR_UNLIKELY(it->second->ShouldRemove() && it->second->CanEvict())) { size_ -= it->second->Size(); + it->second->TakeChildPolicyWrappers(&child_policy_wrappers_to_delete); it = map_.erase(it); } else { ++it; @@ -1503,7 +1538,9 @@ size_t RlsLb::Cache::EntrySizeForKey(const RequestKey& key) { return (key.Size() * 2) + sizeof(Entry); } -void RlsLb::Cache::MaybeShrinkSize(size_t bytes) { +void RlsLb::Cache::MaybeShrinkSize( + size_t bytes, std::vector>* + child_policy_wrappers_to_delete) { while (size_ > bytes) { auto lru_it = lru_list_.begin(); if (GPR_UNLIKELY(lru_it == lru_list_.end())) break; @@ -1515,6 +1552,7 @@ void RlsLb::Cache::MaybeShrinkSize(size_t bytes) { lb_policy_, map_it->second.get(), lru_it->ToString().c_str()); } size_ -= map_it->second->Size(); + map_it->second->TakeChildPolicyWrappers(child_policy_wrappers_to_delete); map_.erase(map_it); } if (GRPC_TRACE_FLAG_ENABLED(rls_lb)) { @@ -1849,13 +1887,18 @@ void RlsLb::RlsRequest::OnRlsCallCompleteLocked(grpc_error_handle error) { response.ToString().c_str()); } std::vector child_policies_to_finish_update; + std::vector> + child_policy_wrappers_to_delete; + OrphanablePtr child_policy_to_delete; { MutexLock lock(&lb_policy_->mu_); if (lb_policy_->is_shutdown_) return; rls_channel_->ReportResponseLocked(response.status.ok()); - Cache::Entry* cache_entry = lb_policy_->cache_.FindOrInsert(key_); + Cache::Entry* cache_entry = + lb_policy_->cache_.FindOrInsert(key_, &child_policy_wrappers_to_delete); child_policies_to_finish_update = cache_entry->OnRlsResponseLocked( - std::move(response), std::move(backoff_state_)); + std::move(response), std::move(backoff_state_), + &child_policy_to_delete); lb_policy_->request_map_.erase(key_); } // Now that we've released the lock, finish the update on any newly @@ -2049,6 +2092,9 @@ absl::Status RlsLb::UpdateLocked(UpdateArgs args) { } } // Now grab the lock to swap out the state it guards. + std::vector> + child_policy_wrappers_to_delete; + OrphanablePtr child_policy_to_delete; { MutexLock lock(&mu_); // Swap out RLS channel if needed. @@ -2060,7 +2106,8 @@ absl::Status RlsLb::UpdateLocked(UpdateArgs args) { // Resize cache if needed. if (old_config == nullptr || config_->cache_size_bytes() != old_config->cache_size_bytes()) { - cache_.Resize(static_cast(config_->cache_size_bytes())); + cache_.Resize(static_cast(config_->cache_size_bytes()), + &child_policy_wrappers_to_delete); } // Start update of child policies if needed. if (update_child_policies) { @@ -2068,14 +2115,12 @@ absl::Status RlsLb::UpdateLocked(UpdateArgs args) { gpr_log(GPR_INFO, "[rlslb %p] starting child policy updates", this); } for (auto& p : child_policy_map_) { - p.second->StartUpdate(); + p.second->StartUpdate(&child_policy_to_delete); } } else if (created_default_child) { - if (GRPC_TRACE_FLAG_ENABLED(rls_lb)) { - gpr_log(GPR_INFO, "[rlslb %p] starting default child policy update", - this); - } - default_child_policy_->StartUpdate(); + GRPC_TRACE_LOG(rls_lb, INFO) + << "[rlslb " << this << "] starting default child policy update"; + default_child_policy_->StartUpdate(&child_policy_to_delete); } } // Now that we've released the lock, finish update of child policies. @@ -2141,14 +2186,20 @@ void RlsLb::ShutdownLocked() { gpr_log(GPR_INFO, "[rlslb %p] policy shutdown", this); } registered_metric_callback_.reset(); - MutexLock lock(&mu_); - is_shutdown_ = true; - config_.reset(DEBUG_LOCATION, "ShutdownLocked"); + RefCountedPtr child_policy_to_delete; + std::vector> + child_policy_wrappers_to_delete; + OrphanablePtr rls_channel_to_delete; + { + MutexLock lock(&mu_); + is_shutdown_ = true; + config_.reset(DEBUG_LOCATION, "ShutdownLocked"); + child_policy_wrappers_to_delete = cache_.Shutdown(); + request_map_.clear(); + rls_channel_to_delete = std::move(rls_channel_); + child_policy_to_delete = std::move(default_child_policy_); + } channel_args_ = ChannelArgs(); - cache_.Shutdown(); - request_map_.clear(); - rls_channel_.reset(); - default_child_policy_.reset(); } void RlsLb::UpdatePickerAsync() { diff --git a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec index 366fadd251..8f9e49415e 100644 --- a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCCppPlugin' - v = '1.65.4' + v = '1.65.5' s.version = v s.summary = 'The gRPC ProtoC plugin generates C++ files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 334cd0ab53..e3ee1c8bc4 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.65.4' + v = '1.65.5' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/version.h b/src/objective-c/GRPCClient/version.h index fdc43b51a6..024abec4e1 100644 --- a/src/objective-c/GRPCClient/version.h +++ b/src/objective-c/GRPCClient/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.65.4" +#define GRPC_OBJC_VERSION_STRING @"1.65.5"