Unsolved 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!
-
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
-
Fair enough.
What version of Qt are you using ?
-
@SGaist 5.5
-
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?
-
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?
-
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