diff options
author | evgeniy-kozev <evgeniy-kozev@yandex-team.com> | 2023-01-17 10:32:45 +0300 |
---|---|---|
committer | evgeniy-kozev <evgeniy-kozev@yandex-team.com> | 2023-01-17 10:32:45 +0300 |
commit | f6f2819eefe1380756cac4c73f96f5b4bb279e27 (patch) | |
tree | e332d682f814409508d77bd40f56507c0bf8f19e /contrib/libs | |
parent | a22e2d277cf7a5eb716738d3d29772f222675f6d (diff) | |
download | ydb-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.cc | 21 |
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; } } |