0x1337
0x1337

Reputation: 1114

Qt slot invokes twice

In mainwindow there is a slot MainWindow::establish_connection in which I'm trying to invoke Server::establish_connection in different thread:

void MainWindow::establish_connection(const std::string& nickname,
                                      const std::string& ip, int port)
{ 
    auto thread = new QThread(this);
    remote_server = new Server(nickname, ip, port);

    connect(thread, SIGNAL(started()), remote_server, SLOT(establish_connection()));

    connect(remote_server, SIGNAL(connected()), this, SLOT(connection_established()));

    connect(remote_server, SIGNAL(readyRead()), this, SLOT(handle_reply()));

    connect(remote_server, SIGNAL(error(QAbstractSocket::SocketError)), this,
            SLOT(connection_failed(QAbstractSocket::SocketError)));

    connect(remote_server, SIGNAL(stop_thread()), thread, SLOT(quit()));

    thread->start();
}

Server::establish_connection method:

void Server::establish_connection()
{
    master_socket = std::move(
                std::unique_ptr<QTcpSocket>(new QTcpSocket(nullptr)));

    connect(master_socket.get(), SIGNAL(connected()), SIGNAL(connected()));

    connect(master_socket.get(), SIGNAL(readyRead()), SIGNAL(readyRead()));
    connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)),
            SIGNAL(error(QAbstractSocket::SocketError)));

    master_socket->connectToHost(ip.c_str(), port);
    if (!master_socket->waitForConnected(timeout*1000))
    {
        emit error(master_socket->error());

    }
    emit stop_thread();
}

but when error signal emits, MainWindow::connection_failed invokes twice.

void MainWindow::connection_failed(QAbstractSocket::SocketError e)
{
    QString err_msg = remote_server->get_socket()->errorString();

    qDebug() << err_msg;
}

Output:

"Connection refused"
"Connection refused"

How to prevent this issue?

Upvotes: 0

Views: 656

Answers (1)

Aaron
Aaron

Reputation: 1191

Here you reemit the signal error from master_socket : connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError)));

This seems to be number one to me.

And here you emit it yourself after timeout:

if (!master_socket->waitForConnected(timeout*1000))
{
    emit error(master_socket->error());

}

This seems to be your number two.

I think while you wait for the timeout error() it is already emitted and relayed by your connect(). And afterwards you emit it yourself again. This seems to be super fluent.

Test whether removing this explicit emit does the trick for you.

Alternatively you can put the line connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError))); after your if condition to get all errors from that point on. No need to disconnect.

Or put it in the else branch because you are only interested in any more errors if a connection could be established:

if (!master_socket->waitForConnected(timeout*1000))
{
    emit error(master_socket->error());

} else {

   connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)),
        SIGNAL(error(QAbstractSocket::SocketError)));
}

Both should work.

Upvotes: 1

Related Questions