|
|
|
@ -127,6 +127,11 @@ void ServerTryCancelNonblocking(experimental::CallbackServerContext* context) { |
|
|
|
|
|
|
|
|
|
Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, |
|
|
|
|
EchoResponse* response) { |
|
|
|
|
if (request->has_param() && request->param().server_notify_started()) { |
|
|
|
|
signaller_.SignalClientRpcStarted(); |
|
|
|
|
signaller_.ServerWaitToContinue(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// A bit of sleep to make sure that short deadline tests fail
|
|
|
|
|
if (request->has_param() && request->param().server_sleep_us() > 0) { |
|
|
|
|
gpr_sleep_until( |
|
|
|
@ -416,19 +421,37 @@ experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( |
|
|
|
|
: service_(service), ctx_(ctx), req_(request), resp_(response) { |
|
|
|
|
// It should be safe to call IsCancelled here, even though we don't know
|
|
|
|
|
// the result. Call it asynchronously to see if we trigger any data races.
|
|
|
|
|
// Join it in OnDone (technically that could be blocking but shouldn't be
|
|
|
|
|
// for very long).
|
|
|
|
|
async_cancel_check_ = std::thread([this] { (void)ctx_->IsCancelled(); }); |
|
|
|
|
|
|
|
|
|
if (request->has_param() && request->param().server_sleep_us() > 0) { |
|
|
|
|
started_ = true; |
|
|
|
|
|
|
|
|
|
if (request->has_param() && request->param().server_notify_started()) { |
|
|
|
|
service->signaller_.SignalClientRpcStarted(); |
|
|
|
|
// Block on the "wait to continue" decision in a different thread since
|
|
|
|
|
// we can't tie up an EM thread with blocking events. We can join it in
|
|
|
|
|
// OnDone since it would definitely be done by then.
|
|
|
|
|
rpc_wait_thread_ = std::thread([this] { |
|
|
|
|
service_->signaller_.ServerWaitToContinue(); |
|
|
|
|
StartRpc(); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
StartRpc(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void StartRpc() { |
|
|
|
|
if (req_->has_param() && req_->param().server_sleep_us() > 0) { |
|
|
|
|
// Set an alarm for that much time
|
|
|
|
|
alarm_.experimental().Set( |
|
|
|
|
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), |
|
|
|
|
gpr_time_from_micros( |
|
|
|
|
request->param().server_sleep_us(), GPR_TIMESPAN)), |
|
|
|
|
gpr_time_from_micros(req_->param().server_sleep_us(), |
|
|
|
|
GPR_TIMESPAN)), |
|
|
|
|
[this](bool ok) { NonDelayed(ok); }); |
|
|
|
|
} else { |
|
|
|
|
NonDelayed(true); |
|
|
|
|
} |
|
|
|
|
started_ = true; |
|
|
|
|
} |
|
|
|
|
void OnSendInitialMetadataDone(bool ok) override { |
|
|
|
|
EXPECT_TRUE(ok); |
|
|
|
@ -448,6 +471,9 @@ experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( |
|
|
|
|
} |
|
|
|
|
EXPECT_EQ(ctx_->IsCancelled(), on_cancel_invoked_); |
|
|
|
|
async_cancel_check_.join(); |
|
|
|
|
if (rpc_wait_thread_.joinable()) { |
|
|
|
|
rpc_wait_thread_.join(); |
|
|
|
|
} |
|
|
|
|
delete this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -575,6 +601,7 @@ experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( |
|
|
|
|
bool started_{false}; |
|
|
|
|
bool on_cancel_invoked_{false}; |
|
|
|
|
std::thread async_cancel_check_; |
|
|
|
|
std::thread rpc_wait_thread_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return new Reactor(this, context, request, response); |
|
|
|
|