snooker9
snooker9

Reputation: 53

gRPC assertion failed when stopping async helloworld server

I'm trying to shutdown properly a gRPC server.
I use the provided async helloworld from gRPC source.
The file is here: https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_async_server.cc

I have edited the main like the following:

#include "greeter_async_server.cc"
#include <thread>
#include <iostream>

void stop_task(ServerImpl* server) {
    int delay = 10000;
    std::cout << "Server will stop after " << delay / 1000 << " seconds" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(delay));
    std::cout << "Wait finished" << std::endl;
    std::cout << "Stoping server..." << std::endl;
    server->Shutdown();
    std::cout << "Stop sent" << std::endl;
}

void server_task(ServerImpl* server) {
    server->Run();
}

int main(int argc, char** argv) {
    ServerImpl server;

    std::thread server_thread(server_task, &server);
    std::thread stop_thread(stop_task, &server);

    stop_thread.join();
    server_thread.join();
    std::cout << "Server stopped" << std::endl;
    return 0;
}
void ServerImpl::Shutdown()
{
    server->Shutdown();
    // Always shutdown the completion queue after the server.
    cq->Shutdown();
}
Server will stop after 10 seconds
Server listening on 0.0.0.0:50051
Wait finished
Stoping server...
E0825 15:08:30.182000000 34960 greeter_async_server.cc:156] assertion failed: ok

Sortie de TestGreeterAsyncServer.exe (processus 37008). Code : -1073740791.
Appuyez sur une touche pour fermer cette fenêtre. . .

I don't understand why the server crashes on assertion failed. The assertion is at line 156:

GPR_ASSERT(ok);

Anyone has an idea?

Thank you in advance!

Upvotes: 0

Views: 1744

Answers (2)

Chnossos
Chnossos

Reputation: 10486

You're trying to delete an object (server) that's been created on the stack.


That said, the example code does not showcase any way to cleanly stop the server once it's been started. It is even said in a comment above the Run() method:

There is no shutdown handling in this code.

This question provides good pointers on how to accomplish your goal.


Here is why the assertion is triggered:

cq_->Next(&tag, &ok); is a blocking call, until either

  • An error occurs (which means ok == false) ;
  • A task is about to be processed (which means ok == true) ;
  • cq_->Shutdown() has been called (which also means ok == false).

You can read about all the different scenarios in CompletionQueue::Next() documentation. Since you're shutting down, ok is false which triggers the assertion's failure.

Upvotes: 2

snooker9
snooker9

Reputation: 53

Here is the solution. I have edited the greeter_async_server.cc like this:

private:
    // Adding attrbutes
    bool is_shutting_down = false;
    std::mutex mutex;

    void HandleRpcs() {
        new CallData(&service_, cq_.get());
        void* tag;
        bool ok;
        while (true) {
            GPR_ASSERT(cq_->Next(&tag, &ok));
            // Here, added exit condition
            mutex.lock();
            if (true == is_shutting_down) {
                mutex.unlock();
                std::cout << "stop reading" << std::endl;
                break;
            }
            else mutex.unlock();
            GPR_ASSERT(ok);
            static_cast<CallData*>(tag)->Proceed();
        }
    }

public:
    // Adding Shutdown public method
    void Shutdown() {
        mutex.lock();
        is_shutting_down = true;
        mutex.unlock();

        const std::chrono::milliseconds WaitDuration = std::chrono::milliseconds(50);
        const std::chrono::time_point<std::chrono::system_clock> Deadline = std::chrono::system_clock::now() + WaitDuration;

        server_->Shutdown(Deadline);
        cq_->Shutdown();
    }

Upvotes: 0

Related Questions