Deadlock inside gRPC Read() function

大兔子大兔子 提交于 2020-01-07 03:18:27

问题


I am working on a C++ project, which uses Google Pub/Sub.

As there is no native support for Google Pub/Sub in C++, I am using it through gRPC. Thus, I have generated corresponding pubsub.grpc.pb.h, pubsub.grpc.pb.cc, pubsub.pb.h and pubsub.pb.cc files via protoc.

I wrote a lightweight wrapper-class, for subscription management. Class basically creates a new thread and starts listening for new messages. Here is the code example (code was built based on this question):

class Consumer 
{
public:
    Consumer();
    ~Consumer();
    void startConsume();
// ...
    std::string m_subscriptionName;
    std::unique_ptr<std::thread> m_thread;
    std::shared_ptr<grpc::Channel> m_channel;
    std::unique_ptr<google::pubsub::v1::Subscriber::Stub> m_stub;
    std::atomic<bool> m_runThread;
};

Consumer::Consumer()
{
    m_channel = grpc::CreateChannel("pubsub.googleapis.com:443", grpc::GoogleDefaultCredentials());
    m_stub = google::pubsub::v1::Subscriber::NewStub(m_channel);
    m_subscriptionName = "something";
}

Consumer::~Consumer()
{
    m_runThread = false;
    if (m_thread && m_thread->joinable())
    {
        m_thread->join();
    }
}

void Consumer::startConsume()
{
    m_thread.reset(new std::thread([this]()
    {
        m_runThread = true;
        while (m_runThread)
        {
            grpc::ClientContext context;
            std::unique_ptr<grpc::ClientReaderWriter<google::pubsub::v1::StreamingPullRequest, 
                                                     google::pubsub::v1::StreamingPullResponse>> stream(m_stub->StreamingPull(&context));
            // send the initial message
            google::pubsub::v1::StreamingPullRequest req;
            req.set_subscription(m_subscriptionName);
            req.set_stream_ack_deadline_seconds(10);

            // if write passed successfully, start subscription
            if (!stream->Write(req))
            {
                continue;
            }

            // receive messages
            google::pubsub::v1::StreamingPullResponse response;
            while (stream->Read(&response))
            {
                google::pubsub::v1::StreamingPullRequest ack_request;
                for (const auto& message : response.received_messages())
                {
                    // process messages ...
                    ack_request.add_ack_ids(message.ack_id());
                }
                stream->Write(ack_request);
            }
        }
    }));
}

Several instances of the Consumer class are created within a process.

It seems works fine. However sometimes program stucks on stream->Read(&response)code. Debugging showed that thread was stuck inside of Read() function call - the stream does not read anything and does not exit from function either, despite that Pub/Sub buffer is not empty. After restarting the application, all messages are successfully read. It seems like a deadlock inside of Read().

Is there anything that I am doing wrong? What can cause this behavior?

来源:https://stackoverflow.com/questions/58569932/deadlock-inside-grpc-read-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!