Skip to content

Commit

Permalink
SocketApi: Fix crash with readyRead() after disconnected() #7044
Browse files Browse the repository at this point in the history
With the recent bugfix to avoid sending messages on dead connections
0bfe7ac
the client now crashed if readyRead() was received after disconnected()
for the socket as the listener for that connection was already removed.

This code fixes it by still invoking the handler from readyRead() but
passing a SocketListener that won't attempt to send messages.
  • Loading branch information
ckamm committed Feb 18, 2019
1 parent f42fdc6 commit d4606d0
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/gui/socketapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,20 @@ class BloomFilter
class SocketListener
{
public:
QIODevice *socket;
QPointer<QIODevice> socket;

SocketListener(QIODevice *socket = 0)
explicit SocketListener(QIODevice *socket)
: socket(socket)
{
}

void sendMessage(const QString &message, bool doWait = false) const
{
if (!socket) {
qCInfo(lcSocketApi) << "Not sending message to dead socket:" << message;
return;
}

qCInfo(lcSocketApi) << "Sending SocketAPI message -->" << message << "to" << socket;
QString localMessage = message;
if (!localMessage.endsWith(QLatin1Char('\n'))) {
Expand Down Expand Up @@ -280,7 +285,19 @@ void SocketApi::slotReadSocket()
{
QIODevice *socket = qobject_cast<QIODevice *>(sender());
ASSERT(socket);
SocketListener *listener = &*std::find_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket));

// Find the SocketListener
//
// It's possible for the disconnected() signal to be triggered before
// the readyRead() signals are received - in that case there won't be a
// valid listener. We execute the handler anyway, but it will work with
// a SocketListener that doesn't send any messages.
static auto noListener = SocketListener(nullptr);
SocketListener *listener = &noListener;
auto listenerIt = std::find_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket));
if (listenerIt != _listeners.end()) {
listener = &*listenerIt;
}

while (socket->canReadLine()) {
// Make sure to normalize the input from the socket to
Expand Down

0 comments on commit d4606d0

Please sign in to comment.