diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-07-12 14:18:18 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-07-12 14:18:18 +0200 |
commit | e7f9a6bf8f681daef1b4157bbac8670c47bd2120 (patch) | |
tree | 7cb3ea4b80fa3a53ea8e6c59538cf02666ebdb1b /common/listener.cpp | |
parent | 38f7eca10b62548825bc6a9e7cadf27c7ece1827 (diff) | |
download | sink-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.cpp | 33 |
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() | |||
177 | void Listener::onDataAvailable() | 178 | void 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 | ||
326 | void Listener::quit() | 324 | void 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 | |||
336 | void 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 | ||
342 | bool Listener::processClientBuffer(Client &client) | 350 | bool 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 | ||