aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authorevgeniy-kozev <evgeniy-kozev@yandex-team.com>2023-01-17 10:32:45 +0300
committerevgeniy-kozev <evgeniy-kozev@yandex-team.com>2023-01-17 10:32:45 +0300
commitf6f2819eefe1380756cac4c73f96f5b4bb279e27 (patch)
treee332d682f814409508d77bd40f56507c0bf8f19e /contrib/libs
parenta22e2d277cf7a5eb716738d3d29772f222675f6d (diff)
downloadydb-f6f2819eefe1380756cac4c73f96f5b4bb279e27.tar.gz
Fix for a racy WorkSerializer shutdown
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/work_serializer.cc21
1 files changed, 13 insertions, 8 deletions
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/work_serializer.cc b/contrib/libs/grpc/src/core/lib/iomgr/work_serializer.cc
index 3af315ccb1..dab378c64d 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/work_serializer.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/work_serializer.cc
@@ -121,10 +121,9 @@ void WorkSerializer::WorkSerializerImpl::Orphan() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_work_serializer_trace)) {
gpr_log(GPR_INFO, "WorkSerializer::Orphan() %p", this);
}
- uint64_t prev_ref_pair =
+ const uint64_t prev_ref_pair =
refs_.fetch_sub(MakeRefPair(0, 1), std::memory_order_acq_rel);
- if (GetSize(prev_ref_pair) == 1) {
- GPR_DEBUG_ASSERT(GetOwners(prev_ref_pair) == 0);
+ if (GetOwners(prev_ref_pair) == 0 && GetSize(prev_ref_pair) == 1) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_work_serializer_trace)) {
gpr_log(GPR_INFO, " Destroying");
}
@@ -170,13 +169,19 @@ void WorkSerializer::WorkSerializerImpl::DrainQueueOwned() {
return;
}
if (GetSize(prev_ref_pair) == 2) {
- // Queue drained. Give up ownership but only if queue remains empty. Note
- // that we are using relaxed memory order semantics for the load on
- // failure since we don't care about that value.
+ // Queue drained. Give up ownership but only if queue remains empty.
uint64_t expected = MakeRefPair(1, 1);
if (refs_.compare_exchange_strong(expected, MakeRefPair(0, 1),
- std::memory_order_acq_rel,
- std::memory_order_relaxed)) {
+ std::memory_order_acq_rel)) {
+ // Queue is drained.
+ return;
+ }
+ if (GetSize(expected) == 0) {
+ // WorkSerializer got orphaned while this was running
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_work_serializer_trace)) {
+ gpr_log(GPR_INFO, " Queue Drained. Destroying");
+ }
+ delete this;
return;
}
}