diff --git a/src/cpp/common/alarm.cc b/src/cpp/common/alarm.cc index 2757350d47d..d3750c9f7f1 100644 --- a/src/cpp/common/alarm.cc +++ b/src/cpp/common/alarm.cc @@ -25,6 +25,7 @@ #include #include #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/surface/completion_queue.h" @@ -81,9 +82,16 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { Ref(); GRPC_CLOSURE_INIT(&on_alarm_, [](void* arg, grpc_error* error) { - AlarmImpl* alarm = static_cast(arg); - alarm->callback_(error == GRPC_ERROR_NONE); - alarm->Unref(); + grpc_core::Executor::Run( + GRPC_CLOSURE_CREATE( + [](void* arg, grpc_error* error) { + AlarmImpl* alarm = + static_cast(arg); + alarm->callback_(error == GRPC_ERROR_NONE); + alarm->Unref(); + }, + arg, nullptr), + error); }, this, grpc_schedule_on_exec_ctx); grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline), diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc index 4d410a5d460..e0a3d15debe 100644 --- a/test/cpp/common/alarm_test.cc +++ b/test/cpp/common/alarm_test.cc @@ -304,6 +304,26 @@ TEST(AlarmTest, CallbackCancellation) { [c] { return c->completed; })); } +TEST(AlarmTest, CallbackCancellationLocked) { + Alarm alarm; + + auto c = std::make_shared(); + alarm.experimental().Set( + std::chrono::system_clock::now() + std::chrono::seconds(10), + [c](bool ok) { + EXPECT_FALSE(ok); + std::lock_guard l(c->mu); + c->completed = true; + c->cv.notify_one(); + }); + std::unique_lock l(c->mu); + alarm.Cancel(); + + EXPECT_TRUE(c->cv.wait_until( + l, std::chrono::system_clock::now() + std::chrono::seconds(1), + [c] { return c->completed; })); +} + TEST(AlarmTest, SetDestruction) { CompletionQueue cq; void* junk = reinterpret_cast(1618033);