ramtheconqueror
ramtheconqueror

Reputation: 1964

QProcess and QLocalSocket - IPC messages aren't received

Following the Fortune Client example.

Have a subclass of QLocalServer which starts the another application (client) using the Qprocess and this client will send some messages using the QLocalSocket. Only the first message from the client appears in the main (server) application that too only when the client process exits.

server app:

localserver.h

#ifndef LOCALSERVER_H
#define LOCALSERVER_H

#include <QLocalServer>

class LocalServer : public QLocalServer
{
    Q_OBJECT

public:

    explicit LocalServer(QObject* prnt = nullptr);
};

#endif // LOCALSERVER_H

localserver.cpp

#include "localserver.h"

#include <QLocalSocket>
#include <QDebug>

LocalServer::LocalServer(QObject* prnt)
    : QLocalServer(prnt)
{
    connect(this, &QLocalServer::newConnection, this, [&]() {
        qDebug() << "Socket connected";
        QLocalSocket* socket = this->nextPendingConnection();
        connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater);
        connect(socket, &QLocalSocket::readyRead, [&, socket]() {
            qDebug() << socket->readAll();
        });
    });
}

main.cpp (server)

#include <QCoreApplication>
#include <QProcess>

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv);

    LocalServer::removeServer("testServer");
    LocalServer server;

    if (server.listen("testServer")) {
        QProcess process;
        process.setProgram("/home/ram/work/build/QtExamples/build-LocalSocketClient-Qt_5_12_1_Desktop-Debug/LocalSocketClient");
        process.start();

        if (process.waitForStarted() && process.waitForFinished()) {
            a.exit(0);
        }
    }

    return a.exec();
}

client app:

main.cpp (client)

#include <QCoreApplication>

#include <QLocalSocket>
#include <QTimer>
#include <QDebug>

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv);

    QLocalSocket localSocket;

    QObject::connect(&localSocket, &QLocalSocket::connected, &localSocket, []() {
        qDebug() << "Socket connected";
    });

    localSocket.setServerName("testServer");
    localSocket.connectToServer();

    if (localSocket.waitForConnected()) {
        qDebug() << "Connected!";
        auto timer = new QTimer(qApp);
        QObject::connect(timer, &QTimer::timeout, &localSocket, [&localSocket]() {
            static int msgCount(0);
            QString msg(QString("Message from client %1").arg(++msgCount));
            qDebug() << localSocket.write(msg.toLatin1()) << msg;

            if (msgCount > 5) {
                qApp->exit(0);
            }
        });
        timer->start(1000);
    } else {
        return 1;
    }

    return a.exec();
}

When I run two applications separately i.e., without Qprocess part in main.cpp in server app, I see the following output.

Socket connected
"Message from client 1"
"Message from client 2"
"Message from client 3"
"Message from client 4"
"Message from client 5"

With QProcess all the five messages appear all at once.

Socket connected
"Message from client 1Message from client 2Message from client 3Message from client 4Message from client 5"

Am I missing anything here? Do QProcess need anymore info?

Also, i have tried using system() function as well - it behaved the same.

Upvotes: 3

Views: 1435

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

Never use the waitXXX methods because they block the event loop inpidiendo that the signals are transmitted. In your case the data is obtained one by one but because no one consumes the information since the signal is not transmitted it accumulates in the buffer and only shows when the eventloop is not blocked showing all the text. So the solution in your case is not to use waitXXX but to use the signals:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    LocalServer::removeServer("testServer");
    LocalServer server;

    if (server.listen("testServer")) {
        QProcess process;
        process.setProgram("/home/ram/work/build/QtExamples/build-LocalSocketClient-Qt_5_12_1_Desktop-Debug/LocalSocketClient");
        process.start();
        QObject::connect(&process, QOverload<int>::of(&QProcess::finished), &QCoreApplication::quit);
        return a.exec();
    }
    return 0;
}

Upvotes: 2

Related Questions