summaryrefslogtreecommitdiffstats
path: root/common/listener.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-07-12 14:18:18 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-07-12 14:18:18 +0200
commite7f9a6bf8f681daef1b4157bbac8670c47bd2120 (patch)
tree7cb3ea4b80fa3a53ea8e6c59538cf02666ebdb1b /common/listener.cpp
parent38f7eca10b62548825bc6a9e7cadf27c7ece1827 (diff)
downloadsink-e7f9a6bf8f681daef1b4157bbac8670c47bd2120.tar.gz
sink-e7f9a6bf8f681daef1b4157bbac8670c47bd2120.zip
Immediately stop processing commands on shutdown.
We send the command completion, then the shutdown notificaiton, and then we immediately shutdown. Otherwise we risk callbacks by further commands into the already destroyed resource.
Diffstat (limited to 'common/listener.cpp')
-rw-r--r--common/listener.cpp33
1 files changed, 23 insertions, 10 deletions
diff --git a/common/listener.cpp b/common/listener.cpp
index 2c5c1df..6f86ee5 100644
--- a/common/listener.cpp
+++ b/common/listener.cpp
@@ -45,7 +45,8 @@ Listener::Listener(const QByteArray &resourceInstanceIdentifier, const QByteArra
45 m_resourceName(resourceType), 45 m_resourceName(resourceType),
46 m_resourceInstanceIdentifier(resourceInstanceIdentifier), 46 m_resourceInstanceIdentifier(resourceInstanceIdentifier),
47 m_clientBufferProcessesTimer(new QTimer(this)), 47 m_clientBufferProcessesTimer(new QTimer(this)),
48 m_messageId(0) 48 m_messageId(0),
49 m_exiting(false)
49{ 50{
50 connect(m_server.get(), &QLocalServer::newConnection, this, &Listener::acceptConnection); 51 connect(m_server.get(), &QLocalServer::newConnection, this, &Listener::acceptConnection);
51 SinkTrace() << "Trying to open " << m_resourceInstanceIdentifier; 52 SinkTrace() << "Trying to open " << m_resourceInstanceIdentifier;
@@ -177,7 +178,7 @@ void Listener::checkConnections()
177void Listener::onDataAvailable() 178void Listener::onDataAvailable()
178{ 179{
179 QLocalSocket *socket = qobject_cast<QLocalSocket *>(sender()); 180 QLocalSocket *socket = qobject_cast<QLocalSocket *>(sender());
180 if (!socket) { 181 if (!socket || m_exiting) {
181 return; 182 return;
182 } 183 }
183 readFromSocket(socket); 184 readFromSocket(socket);
@@ -270,9 +271,7 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
270 break; 271 break;
271 case Sink::Commands::ShutdownCommand: 272 case Sink::Commands::ShutdownCommand:
272 SinkLog() << QString("Received shutdown command from %1").arg(client.name); 273 SinkLog() << QString("Received shutdown command from %1").arg(client.name);
273 // Immediately reject new connections 274 m_exiting = true;
274 m_server->close();
275 QTimer::singleShot(0, this, &Listener::quit);
276 break; 275 break;
277 case Sink::Commands::PingCommand: 276 case Sink::Commands::PingCommand:
278 SinkTrace() << QString("Received ping command from %1").arg(client.name); 277 SinkTrace() << QString("Received ping command from %1").arg(client.name);
@@ -292,8 +291,7 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
292 SinkLog() << QString("Received a remove from disk command from %1").arg(client.name); 291 SinkLog() << QString("Received a remove from disk command from %1").arg(client.name);
293 m_resource.reset(nullptr); 292 m_resource.reset(nullptr);
294 loadResource().removeDataFromDisk(); 293 loadResource().removeDataFromDisk();
295 m_server->close(); 294 m_exiting = true;
296 QTimer::singleShot(0, this, &Listener::quit);
297 } break; 295 } break;
298 default: 296 default:
299 if (commandId > Sink::Commands::CustomCommand) { 297 if (commandId > Sink::Commands::CustomCommand) {
@@ -323,7 +321,7 @@ qint64 Listener::lowerBoundRevision()
323 return lowerBound; 321 return lowerBound;
324} 322}
325 323
326void Listener::quit() 324void Listener::sendShutdownNotification()
327{ 325{
328 // Broadcast shutdown notifications to open clients, so they don't try to restart the resource 326 // Broadcast shutdown notifications to open clients, so they don't try to restart the resource
329 auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Notification::Shutdown); 327 auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Notification::Shutdown);
@@ -333,10 +331,20 @@ void Listener::quit()
333 Sink::Commands::write(client.socket, ++m_messageId, Sink::Commands::NotificationCommand, m_fbb); 331 Sink::Commands::write(client.socket, ++m_messageId, Sink::Commands::NotificationCommand, m_fbb);
334 } 332 }
335 } 333 }
334}
335
336void Listener::quit()
337{
338 m_clientBufferProcessesTimer->stop();
339 m_server->close();
340 sendShutdownNotification();
341 closeAllConnections();
336 m_fbb.Clear(); 342 m_fbb.Clear();
337 343
338 // Connections will be cleaned up later 344 QTimer::singleShot(0, this, [this]() {
339 emit noClients(); 345 // This will destroy this object
346 emit noClients();
347 });
340} 348}
341 349
342bool Listener::processClientBuffer(Client &client) 350bool Listener::processClientBuffer(Client &client)
@@ -369,6 +377,10 @@ bool Listener::processClientBuffer(Client &client)
369 SinkLog() << QString("Socket became invalid before we could send a response. client: %1").arg(clientName); 377 SinkLog() << QString("Socket became invalid before we could send a response. client: %1").arg(clientName);
370 } 378 }
371 }); 379 });
380 if (m_exiting) {
381 quit();
382 return false;
383 }
372 384
373 return client.commandBuffer.size() >= headerSize; 385 return client.commandBuffer.size() >= headerSize;
374 } 386 }
@@ -446,6 +458,7 @@ Sink::Resource &Listener::loadResource()
446 m_resource = std::unique_ptr<Sink::Resource>(new Sink::Resource); 458 m_resource = std::unique_ptr<Sink::Resource>(new Sink::Resource);
447 } 459 }
448 } 460 }
461 Q_ASSERT(m_resource);
449 return *m_resource; 462 return *m_resource;
450} 463}
451 464