I've got a server class that has a `start` method and a `stop` method. The listening port is unknown until a user calls start.
As such, I build the server there, something like:
void GrpcStreamingServerImpl::start(QUrl const& endpoint)
{
stop();
::grpc::ServerBuilder builder;
builder.AddListeningPort(endpoint.toString().toStdString(), grpc::InsecureServerCredentials());
builder.RegisterService(&m_service);
m_completionQueueCalls = builder.AddCompletionQueue();
m_completionQueueNotifications = builder.AddCompletionQueue();
m_server = builder.BuildAndStart();
m_running = true;
....
and then I tear everything down when the server stops. Something like:
if(!m_running)
{
return;
}
m_running = false;
{
std::lock_guard<std::mutex> local_lock_guard {m_mutexSessions};
for(const auto& it : m_sessions)
{
it.second->finish();
}
}
if(m_server)
{
m_server->Shutdown();
m_completionQueueCalls->Shutdown();
m_completionQueueNotifications->Shutdown();
// Wait for the threads to exit before allowing the destruction of the completion queues they use
if(m_callQueueThread && m_callQueueThread->isRunning() )
{
m_callQueueThread->wait();
}
if(m_notificationQueueThread && m_notificationQueueThread->isRunning())
{
m_notificationQueueThread->wait();
}
delete m_completionQueueNotifications;
delete m_completionQueueCalls;
delete m_server;
....
Problem is, if the user wants to start, stop, and start again, the RegisterService call results in abort being called and complains a service is already registered.
I tried to move the registration part to the constructor and only add a listening port when start() is called, but that results in a seg fault. Builder isn't a singleton, although I dunno how or why it retains the registration after the server object it returned was destroyed.
A little googling and I found issues were submitted regarding this, but there are no plans to implement an "unregisterService" method. So, what does one to work around this problem?