why GRPC AsyncClient throws Segfault when waiting for the Next result in the completion queue

Viewed 1699

I am using version 1.23.1 of the GRPC library.

I have an asynchronous RPC c++ Client class, which initiates each RPC with the following method:

void Client::SendTaskAsync(const Task& task) {
    unique_lock<mutex> lock(mtx_);
    cout << "Sending task with id " << task.id() << endl;
    ClientContext context;
    Status status;
    unique_ptr<ClientAsyncResponseReader<Result>> rpc(
        stub_->PrepareAsyncSendTask(&context, task, &queue_));
    rpc->StartCall();
    // Allocating memory to store result from RPC
    Result* result = &results_.emplace_back();
    int* tag = new int(results_.size() - 1);
    rpc->Finish(result, &status, static_cast<void*>(tag));
}

In the main thread I call SendTaskAsync five times in a loop.

The Client class has a background thread informing when each RPC has returned a Result:

while (true) {
    void* tag;
    bool ok = false;
    {
        unique_lock<mutex> lock(mtx_);
        cout << "Waiting the for next result" << endl;
        const time_point<system_clock> deadline = 
            system_clock::now() + milliseconds(1000);
        // SEGFAULT HERE, WHY?
        GPR_ASSERT(queue_.AsyncNext(&tag, &ok, deadline));
    }
    if (ok) {
        int index = *static_cast<int*>(tag);
        cout << "Got result with tag " << index << endl;
    } else {
        cout << "Sleeping" << endl;
        sleep_for(milliseconds(1000));
    }
}

If I start my client, the following log is observed:

BACKGROUND:  Waiting for the next result
MAIN THREAD: Sending task with id 0
BACKGROUND:  Sleeping
MAIN THREAD: Sending task with id 1
MAIN THREAD: Sending task with id 2
MAIN THREAD: Sending task with id 3
MAIN THREAD: Sending task with id 4
BACKGROUND:  Waiting for the next result
BACKGROUND:  Segmentation fault (core dumped)

What happens is that

  • Background thread checks if a queue_ contains a result, there is none yet, so it goes to sleep;

  • Main thread makes 5 RPC that at the end should populate the queue_ with results;

  • Background thread wakes up and checks if a queue_ contains a result, AND CRASHES.

Any ideas why?

1 Answers

The code in the question is written according to this tutorial, which sends only one request and waits for a reply in the same thread.

If you want to use multiple threads, follow the client example here.

Related