-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Pure virtual method called" exception #20
Comments
Hi, thank you for reporting the issue. I have trouble reproducing it. This email conversion in gRPC suggests that you might be doing two asynchronous operations in parallel that are not allowed to be in parallel. E.g. writing and finishing a I do not know what you mean by asio::awaitable<void> handle_request(grpc::ServerContext& server_context, auto& request, auto& writer, agrpc::GrpcContext& grpc_context)
{
// This function will be called for each request from the client as soon as the request has been made, even while
// a previous request is still being processed by `handle_request`.
// It is executing on a thread of the system_context.
co_return;
}
void register_handler(asio::system_context& ctx, agrpc::GrpcContext& grpc_context, MarketDataAlert::AsyncService& service)
{
agrpc::repeatedly_request(&MarketDataAlert::AsyncService::Requestsubscribe, service,
asio::bind_executor(grpc_context,
[&]<class T>(agrpc::RepeatedlyRequestContext<T>&& context)
{
asio::co_spawn(
ctx,
[&, context = std::move(context)]()
{
auto&& [server_context, request, responder] = context.args();
return std::invoke(handle_request, server_context, request, responder, grpc_context);
},
asio::detached);
}));
} |
Thank you for the very quick response! I'll take a look on the link you have sent. What I meant by "handle one request at a time", is that the first request is processed and receives it's messages but the following requests all receive a unable to connect to server, which I assume is because it is occupied by the first request, which is on the while(request_ok) loop. In other words, i can only have one stream active at a time. It is also happening with the code you provided.
I thought that this would happen too, but apparently is not. I can only start another rpc call when the previous one finishes. Could this be a performance issue? I mean by this is: could my system be too slow to co_spawn and process the new request while the other one is running? |
I suspect that something is blocking the GrpcContext. E.g. in your example: while(request_ok) {
// If `fill_response` performs blocking operations, e.g. holding a lock on a mutex or calling some long
// CPU-intensive task then the entire GrpcContext will be blocked, because `agrpc::write` resumes
// in the thread of the GrpcContext. If that is the case then explicitly switch back to the system_context
// before doing such tasks.
co_await asio::post(asio::bind_executor(ctx, asio::use_awaitable));
co_await fill_response(server_context, request, response, instrumentId);
// do some work
request_ok = co_await agrpc::write(writer, response,
boost::asio::bind_executor(grpc_context, boost::asio::use_awaitable));
}
//after done work
bool finish_ok = co_await agrpc::finish(writer, grpc::Status::OK, boost::asio::bind_executor(grpc_context, boost::asio::use_awaitable)); I have just adjusted one of the unit test to deliberately verify that repeatedly_request can handle multiple requests at the same time which succeeds on all tested platforms/compilers. |
This was indeed the problem. Thank you! Keep up the good work with the library! |
Great, I am glad we figured it out and thank you for the kind words. |
First, let me be clear that i don't know much about the boost library, so maybe my mistake is in that regard. The issue I'm facing is: I have a server-streaming service that needs to send data every x seconds to a client. There could be multiple requests from the same client, as long as the parameters of the request are different as well as multiple clients connected at the same time. To do that, what I did was start a repeatedly_request as shown on issue #14 :
On the handle_request coroutine, if the request is valid, I tried 2 different variations. The first is this:
Which kinda works as I expected except I can only handle one request at a time, which makes it unviable for my use case.
The second attempt was to co_spawn processRequest, as such:
But now, upon calling agrpc::write, I have a "pure virtual method called" exception. As stated on the documentation, since I'm using another context instead of the agrpc::GrpcContext, I always use bind_executor(grpc_context, asio::awaitable).
The processRequest method has the following structure:
I don't know how should I send you the stack trace, but I'll send a printscreen from the IDE.
What am I doing wrong?
Thank you in advance
The text was updated successfully, but these errors were encountered: