I am trying to make the client work with timeouts. For this I modified the async_greeter_server.cpp and async_greeter_client.cpp files to test the concept.
I am setting a deadline on the client side (on the client context) and if there is a timeout I wait until I receive the actual (delayed)response from the server. Following is the change (after the Finish() call).
Similarly on the server side send the response after some delay to produce a timeout at the client.
The server side crashes due to assert in the CallData cq_.Next() loop "GPR_ASSERT(ok)".
The Client keeps waiting for the actual response forever in the added timeout code.
Any idea what's wrong with this program ?
greeter_async_client.cc
std::string SayHello(const std::string& user)
{
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
HelloReply reply;
ClientContext context;
CompletionQueue cq;
Status status;
std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + std::chrono::seconds(10);
context.set_deadline(deadline);
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(stub_->AsyncSayHello(&context, request, &cq));
rpc->Finish(&reply, &status, (void*)1);
void* got_tag;
bool ok = false;
GPR_ASSERT(cq.Next(&got_tag, &ok));
GPR_ASSERT(got_tag == (void*)1);
GPR_ASSERT(ok);
// -------------- HANDLE TIMEOUT ------------------------------------------
// If timeout error wait for the actual reply
if (status.error_code() == grpc::StatusCode::DEADLINE_EXCEEDED)
{
std::cout << "Timeout exceeded .., waiting for the next event "<< status.error_message() << std::endl;
GPR_ASSERT(cq.Next(&got_tag, &ok));
GPR_ASSERT(got_tag == (void *) 1);
GPR_ASSERT(ok);
}
// Act upon the status of the actual RPC.
if (status.ok())
{
return reply.message();
}
else
{
return "RPC failed";
}
}
greeter_async_server.cc
void Proceed()
{
if (status_ == CREATE)
{
status_ = PROCESS;
service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_,this);
}
else if (status_ == PROCESS)
{
new CallData(service_, cq_);
std::string prefix("Hello ");
reply_.set_message(prefix + request_.name());
std::cout << "Sleeping for 20 seconds .... \n";
std::this_thread::sleep_for(std::chrono::seconds(20));
std::cout << "Out of sleep ..... \n";
status_ = FINISH;
responder_.Finish(reply_, Status::OK, this);
std::cout <<" Reply sent - Finish ....... \n";
}
else
{
GPR_ASSERT(status_ == FINISH);
// Once in the FINISH state, deallocate ourselves (CallData).
delete this;
}
}