gprc 服务器在处理第二个请求时崩溃

Posted

技术标签:

【中文标题】gprc 服务器在处理第二个请求时崩溃【英文标题】:gprc server was crashed on processed second request 【发布时间】:2017-03-14 15:15:37 【问题描述】:

最近我想在我的网络后端学习使用 grpc,但是一些问题破坏了我的进步

服务器实现

class CGreeterAsyncServerImpl

public:
    CGreeterAsyncServerImpl()
        :run_(true)
    
    ~CGreeterAsyncServerImpl()
        cq_->Shutdown();
        server_->Shutdown();
    

    void stop()  run_ = false; 

    void Run(const char* addr) 
        bool ok = false;
        void* tag = nullptr;
        ServerBuilder builder;
        builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
        builder.RegisterService(&service_);
        cq_ = builder.AddCompletionQueue(true);
        server_ = builder.BuildAndStart();

        std::shared_ptr<CMyAsyncRequest> ReqPtr(new CMyAsyncRequest(&service_, cq_.get()));
        while (run_)
        
            if (!cq_->Next(&tag, &ok)) break;

            if (ok) 
                ReqPtr->Process();
            
        
        std::cout << "run exit." << std::endl;
    
private:
    bool run_;
    Greeter::AsyncService service_;
    std::unique_ptr<Server> server_;
    std::unique_ptr<ServerCompletionQueue> cq_;
;

我的要求实现

class CMyAsyncRequest

public:
    CMyAsyncRequest(Greeter::AsyncService* service,ServerCompletionQueue* cq) 
        :service_(service),
        resp_(&ctx_),
        cq_(cq),
        state_(RequestState::RS_PROCESS)
        service_->RequestSayHello(&ctx_, &req_, &resp_, cq_, cq_, (void*)this);
    

    void Process() 
        switch (state_)
        
            case CMyAsyncRequest::RS_PROCESS:
            
                std::string str("hello ");
                str.append(req_.name());
                reply_.set_message(str);
                resp_.Finish(reply_, Status::OK,(void*)this);
                state_ = RequestState::RS_COMPLETED;
            
            break;
            case CMyAsyncRequest::RS_COMPLETED:
            
                req_.Clear();
                service_->RequestSayHello(&ctx_, &req_, &resp_, cq_, cq_, (void*)this);
                state_ = RequestState::RS_PROCESS;
            
            break;
        
    

    enum RequestState
    
        RS_PROCESS,
        RS_COMPLETED
    ;

    RequestState state_;

    HelloRequest req_;
    HelloReply reply_;

    ServerContext ctx_;
    ServerCompletionQueue *cq_;
    Greeter::AsyncService* service_;
    ServerAsyncResponseWriter<HelloReply> resp_;
;

终于启动服务器

CGreeterAsyncServerImpl server;
server.Run("0.0.0.0:80");

我的服务器在处理第二个 rpc 调用时崩溃了 并且无法从调用堆栈中找到任何有用的信息

    grpc_server_sample.exe!issue_debug_notification(const wchar_t * const message) Line 125 C++
    grpc_server_sample.exe!__acrt_report_runtime_error(const wchar_t * message) Line 142    C++
    grpc_server_sample.exe!abort() Line 51  C++
    grpc_server_sample.exe!grpc::ServerContext::BeginCompletionOp(grpc::Call * call) Line 161   C++
    grpc_server_sample.exe!grpc::ServerInterface::BaseAsyncRequest::FinalizeResult(void * * tag, bool * status) Line 629    C++
    grpc_server_sample.exe!grpc::ServerInterface::PayloadAsyncRequest<sample::HelloRequest>::FinalizeResult(void * * tag, bool * status) Line 202   C++
    grpc_server_sample.exe!grpc::CompletionQueue::AsyncNextInternal(void * * tag, bool * ok, gpr_timespec deadline) Line 76 C++
    grpc_server_sample.exe!grpc::CompletionQueue::Next(void * * tag, bool * ok) Line 152    C++
    grpc_server_sample.exe!CGreeterAsyncServerImpl::Run(const char * addr) Line 218 C++
    grpc_server_sample.exe!main(int argc, char * * argv) Line 244   C++

我的代码与示例代码不同的是,示例代码在完成处理一个请求后创建新的请求上下文,我想为下一个请求重用请求对象。

example code

【问题讨论】:

【参考方案1】:

您需要为每个 rpc 创建一个新对象作为其数据的容器。 ServerContextWriter 不能在 RPC 之间共享。

【讨论】:

有没有办法重用请求上下文? 没有。您需要一些数据结构来表示 rpc,同时对两个 rpc 使用相同的数据结构没有任何意义。

以上是关于gprc 服务器在处理第二个请求时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

从不同的 VC 访问时,带有完成处理程序的 API 调用函数崩溃

尝试保存第二个任务时服务的“并发”错误

AJAX简述

在 Undertow 中读取 POST 请求而不使用它

创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃

当我尝试使用图像按钮进入第二个活动时应用程序崩溃