Hi all,
I've created a tiny code sample that is based off the hello world async greeter example. I keep getting a "pure virtual method called" in the grpc_completion_queue_next() function, and I'm having a hard time understanding why. What am I doing wrong?
I've included the proto file, C++ code and gdb output... (the program is both a client or a server, if you give it a command line value of "c" it acts as a client).
Thanks in advance!
PROTO FILE
syntax = "proto3";
package helloworld;
service Greeter
{
rpc SayHello (HelloRequest) returns (stream HelloReply) {}
}
message HelloRequest
{
string message = 1;
}
message HelloReply
{
string reply = 1;
}
C++ CODE
#include <iostream>#include <string>#include <grpc++/grpc++.h>#include "minfail.grpc.pb.h"using namespace std;using namespace helloworld;class CallData {public: CallData(Greeter::AsyncService* service, grpc::ServerCompletionQueue* cq) : service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) { Proceed(); } void Proceed() { if (status_ == CREATE) { status_ = PROCESS; service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, this); } else if (status_ == PROCESS) { new CallData(service_, cq_); reply_.set_reply("hello " + request_.message()); responder_.Write (reply_, this); responder_.Finish(grpc::Status::OK, this); status_ = FINISH; } else { GPR_ASSERT(status_ == FINISH); delete this; } }private: HelloRequest request_; HelloReply reply_; grpc::ServerAsyncWriter<HelloReply> responder_; enum CallStatus { CREATE, PROCESS, FINISH }; CallStatus status_; grpc::ServerContext ctx_; grpc::ServerCompletionQueue* cq_; Greeter::AsyncService* service_;};class GreeterClient{public: GreeterClient (shared_ptr <grpc::Channel> channel) : stub_ (Greeter::NewStub (channel)) {} string SayHello (const string &user) { HelloRequest request; request.set_message (user); grpc::ClientContext context; unique_ptr <grpc::ClientReader <HelloReply>> reader (stub_->SayHello (&context, request)); HelloReply reply; while (reader -> Read (&reply)) { cout << "SayHello returns " << reply.reply() << "\n"; } grpc::Status status = reader -> Finish(); if (status.ok()) { return (reply.reply()); } return ("<RPC failed>"); }private: unique_ptr<Greeter::Stub> stub_;};intmain (int argc, char **argv){ string server_address ("0.0.0.0:50051"); if (argc == 2 && argv [1][0] == 'c') { GreeterClient greeter(grpc::CreateChannel (server_address, grpc::InsecureChannelCredentials())); cout << "Sending world...\n"; cout << "Response is " << greeter.SayHello ("world") << "\n"; } else { unique_ptr<grpc::ServerCompletionQueue> cq; Greeter::AsyncService service; unique_ptr<grpc::Server> server; grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); cq = builder.AddCompletionQueue(); server = builder.BuildAndStart(); new CallData(&service, cq.get()); CallData* tag; // uniquely identifies a request. bool ok; while (true) { GPR_ASSERT(cq->Next((void **)&tag, &ok)); GPR_ASSERT(ok); tag->Proceed(); } server->Shutdown(); cq->Shutdown(); }} and run / GDB output:
$ ./minfail
D1115 11:45:47.919769500 24264 env_linux.c:77] Warning: insecure environment read function 'getenv' used
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
$ gdb ./minfail
... elided ...
Program received signal SIG36, Real-time event 36.
0x00000035ce0e8cec in epoll_pwait () from /lib64/libc.so.6
(gdb) bt
#0 0x00000035ce0e8cec in epoll_pwait () from /lib64/libc.so.6
#1 0x00007ffff76f8d4a in ?? () from /.../lib/libgrpc++.so.1
#2 0x00007ffff76f91a6 in ?? () from /.../lib/libgrpc++.so.1
#3 0x00007ffff770d61b in grpc_completion_queue_next () from /.../lib/libgrpc++.so.1
#4 0x00007ffff76e3f20 in grpc::CompletionQueue::AsyncNextInternal(void**, bool*, gpr_timespec) () from /.../lib/libgrpc++.so.1
#5 0x000000000040919f in grpc::CompletionQueue::Next [_ZN4grpc15Completion...] (this=0x628fa0, tag=0x7fffffffe1e8, ok=0x7fffffffe1e7) at .../include/grpc++/impl/codegen/completion_queue.h:148
#6 0x00000000004085ca in main [main] (argc=1, argv=0x7fffffffe3a8) at minfail.cc:95
(gdb)
Any help greatly appreciated!
Cheers,
-RK