Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSocketNotifier not activatign on Windows (works for Mac)



  • Hello,
    I am using QSocketNotifier to tail the log of my application to also be shown as messages in the mainwindow statusbar. It took some effort to determine how to do this but I did get it to work on the Mac. When I tried my Windows build, the signals never activate. I did read that Windows is different and requires explicit enable/disables of the notifier, but even adding these did not work.
    The code:
    initialization in main thread:
    @@
    oid cap::setLogs(QString outLog, QString errLog)
    {
    statusWatcher = new StatusWatcher(this, outLog, errLog);
    statusWatcherThread = new QThread(this);
    statusWatcher->moveToThread(statusWatcherThread);
    statusWatcherThread->start();
    connect(statusWatcher, SIGNAL(statusMessage(QString)), this, SLOT(catchStatusMessage(QString)));
    connect(statusWatcher, SIGNAL(toggleNotifier(bool, QSocketNotifier*)), this, SLOT(toggleNotifier(bool, QSocketNotifier*)));
    }
    @@

    the constructor:
    @@
    StatusWatcher::StatusWatcher(QObject *parent, QString outLog, QString errLog)
    {
    if (outLog != "") {
    outLogPath = outLog;
    outFilePtr = fopen(outLogPath.toStdString().c_str(), "r");
    outStream = new QTextStream(outFilePtr, QIODevice::ReadOnly);
    outNotifier = new QSocketNotifier(fileno(outFilePtr), QSocketNotifier::Read);
    connect(outNotifier, SIGNAL(activated(int)), this, SLOT(readChangedLog(int)));
    }
    else {
    outLogPath = "";
    emit statusMessage(tr("output log could not be monitored in status bar"));
    }
    if (errLog != "") {
    errLogPath = errLog;
    errFilePtr = fopen(errLogPath.toStdString().c_str(), "r");
    errStream = new QTextStream(errFilePtr, QIODevice::ReadOnly);
    errNotifier = new QSocketNotifier(fileno(errFilePtr), QSocketNotifier::Read);
    connect(errNotifier, SIGNAL(activated(int)), this, SLOT(readChangedLog(int)));
    }
    else {
    errLogPath = "";
    emit statusMessage(tr("error log could not be monitored in status bar"));
    }
    prefixedMessage.push("CAP Processing: ");
    }
    @@

    the slot called when activate occurs:
    @@
    void StatusWatcher::readChangedLog(int socket)
    {
    if (socket == fileno(outFilePtr)) {
    emit toggleNotifier(false, outNotifier);
    while (!outStream->atEnd()) {
    QString line = outStream->readLine();
    emit statusMessage(line);
    }
    emit toggleNotifier(true, outNotifier);
    }
    else if (socket == fileno(errFilePtr)) {
    emit toggleNotifier(false, errNotifier);
    while (!errStream->atEnd()) {
    QString line = errStream->readLine();
    emit statusMessage(line);
    }
    emit toggleNotifier(true, errNotifier);
    }
    }
    @@

    the slots back in the main thread to enable/disable the notifiers and show the retrieved message:
    @@
    void cap::toggleNotifier(bool state, QSocketNotifier *notifier)
    {
    notifier->setEnabled(state);
    }

    void cap::catchStatusMessage(QString msg)
    {
    ui->statusbar->showMessage(msg);
    }
    @@

    Thank you!


  • Lifetime Qt Champion

    Hi,

    Just to be sure I understand your goal correctly, you want to monitor your own application log file ?

    If so, why not use a custom message handler and process your log messages before sending them to that file ?



  • @SGaist Its a reasonable question! The reason why that doesn't work out as well as that much of the application is engineered as libraries with no Qt-related code, or more specifically, the logging is done by writing to stderr and stdout (which are then subject to a "freopen" to a log file which is what is being tied to the QTextstreams and QSocketNotifiers) rather than using any code that is related to Qt. We do this for a variety of reasons, not least because we re-use the code for fully-automated analyses without any user interface being loaded. Something like this could still be done, for example stubbing out any Qt statusbar related code in the "headless" build, but since I was able to make this work on the Mac and it is really elegant. The documentation suggests this should also work on Windows, so I hope that in fact I can, rather than changing the approach altogether.

    Andy


  • Lifetime Qt Champion

    Fair enough.

    What version of Qt are you using ?



  • @SGaist 5.5


  • Lifetime Qt Champion

    Then I'd first recommend upgrading to 5.6 if possible.



  • @SGaist We're a very small team and trying to converge a release right now. Is there a specific reason for 5.6 with respect to this issue, or a more generalized sense that working with the latest is best?


  • Lifetime Qt Champion

    Best working with the latest if possible and since you're about to do a release, Qt 5.6 is a LTS release which might also be interesting from a maintenance point of view.



  • @SGaist The LTS support matters, thank you for raising that. On the down side, it looks like Qt WebKit is dropped in 5.6, a show stopper for us unless I misunderstand. And while the question of upgrading is percolating, is there any specific rather than general impact on the present issue?


  • Lifetime Qt Champion

    You can still build the module.

    There's was a fix late last year that I'm not sure went in for Qt 5.5 or 5.6


Log in to reply