Hi,

I managed to write a minimal client/server example that causes a crash in 
the client code in RunInterceptor and I was wondering if I'm doing 
something wrong.

*Proto File:*
*syntax = "proto3";*

*package myService;*

*service MyService*
*{*
*  rpc Ping(EmptyMessage) returns (PongResponse) {}*
*  rpc StartStream(EmptyMessage) returns (stream StreamEvent) {}*
*}*

*message EmptyMessage*
*{*
*}*

*message PongResponse*
*{*
*  bool pong = 1;*
*}*

*message StreamEvent*
*{*
*  uint64 value = 1;*
*  uint32 otherValue = 2;*
*  bool yetAnotherValue = 3;*
*}*

*Server File:*














































































*#ifdef _WIN32#    pragma warning(push)#    pragma warning(disable : 4251) 
// Disable dll-class warning#    pragma warning(disable : 4127) // Disable 
conditional expression is constant#endif#include 
"service.grpc.pb.h"#include <grpcpp/grpcpp.h>#ifdef _WIN32#    pragma 
warning(pop)#endif#include <iostream>#include <string>#include 
<chrono>#include <thread>#include <memory>class Service final : public 
myService::MyService::Service{public:    Service(std::string const& uri)    
{        _builder.AddListeningPort(uri, 
grpc::InsecureServerCredentials());        _builder.RegisterService(this);  
  }    void start()    {        _server = _builder.BuildAndStart();    }    
void stop()    {        if (_server != nullptr)        {            
_server->Shutdown();        }    }private:    virtual ::grpc::Status 
Ping(::grpc::ServerContext* /*context*/, const ::myService::EmptyMessage* 
/*request*/, ::myService::PongResponse* response) override    {        
std::cout << "Ping request\n";        response->set_pong(true);        
return grpc::Status::OK;    }    virtual ::grpc::Status 
StartStream(::grpc::ServerContext* /*context*/, const 
::myService::EmptyMessage* /*request*/, 
::grpc::ServerWriter<::myService::StreamEvent>* writer) override    {      
  {            auto evt = myService::StreamEvent{};            
evt.set_value(0x1);            evt.set_othervalue(0x2);            
evt.set_yetanothervalue(false);            writer->Write(evt);        }    
    return grpc::Status::OK;    }    grpc::ServerBuilder _builder{ 
grpc::ServerBuilder{} };    std::unique_ptr<grpc::Server> _server{ nullptr 
};};int main(int /*argc*/, char** /*argv*/){    auto const ServerAddress = 
std::string{ "0.0.0.0:50051" };    auto service = Service{ ServerAddress 
};    service.start();    std::cout << "Server listening on " << 
ServerAddress << std::endl;    
std::this_thread::sleep_for(std::chrono::seconds(3000));    
service.stop();    return 0;}*

*Client File:*





































































*#ifdef _WIN32#    pragma warning(push)#    pragma warning(disable : 4251) 
// Disable dll-class warning#    pragma warning(disable : 4127) // Disable 
conditional expression is constant#    pragma warning(disable : 4702) // 
Disable unreachable code#endif#include "service.grpc.pb.h"#include 
<grpcpp/grpcpp.h>#ifdef _WIN32#    pragma warning(pop)#endif#include 
<iostream>#include <string>class Observer : public 
grpc::ClientReadReactor<myService::StreamEvent>{public:    
Observer(myService::MyService::Stub* stub) noexcept        : _stub{ stub }  
  {        auto context = grpc::ClientContext{};        auto request = 
myService::EmptyMessage{};        _stub->async()->StartStream(&context, 
&request, this);        StartRead(&_event); // Start reading (actually 
postponed until StartCall is called)        StartCall();    }private:    
virtual void OnReadDone(bool ok) override    {        if (ok)        {      
      std::cout << "StreamEvent: " << std::to_string(_event.value()) << " - 
" << std::to_string(_event.othervalue()) << " - " << 
(_event.yetanothervalue() ? "True" : "False") << std::endl;            // 
Read next event            StartRead(&_event);        }    }    
myService::MyService::Stub* _stub{ nullptr };    myService::StreamEvent 
_event{};};int main(int /*argc*/, char** /*argv*/){    auto const 
ServerAddress = std::string{ "127.0.0.1:50051" };    auto channel = 
grpc::CreateChannel(ServerAddress, grpc::InsecureChannelCredentials());    
auto stub = myService::MyService::NewStub(channel);    try    {        auto 
observer = Observer{ stub.get() };        for (auto i = 0; i < 10000; ++i)  
      {            auto context = grpc::ClientContext{};            auto 
request = myService::EmptyMessage{};            auto response = 
myService::PongResponse{};            stub->Ping(&context, request, 
&response);            std::cout << "Ping? " << (response.pong() ? "Yes" : 
"No") << std::endl;        }    }    catch (std::exception const& e)    {  
      std::cout << "RPC Failed: " << e.what() << std::endl;    }    return 
0;}*

The crash occurs when the server writes the StreamEvent (inside the 
StartStream method) in one thread at the same time as a PongResponse (when 
returning from the Ping method) in another thread. But the crash occurs in 
the client code, in the RunInterceptor method.

Is this a bug or am I doing something wrong?
I'm using gRPC 1.41.0 (from vcpkg).
Thanks,
Chris

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to grpc-io+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/6ac07d68-65e4-43c5-8d07-f4e1b6d4f623n%40googlegroups.com.

Reply via email to