Read stderr output from own process
-
wrote on 10 Apr 2014, 14:55 last edited by
Hi there,
currently i'm writing a gui application which uses the external c library "libssh":http://www.libssh.org . This library prints log messages (of adjustable verbosity) on stderr. I would like display them "live" in my gui. So i want the process to read it's own stderr.
First, some clarifications:
The libssh stuff runs (blocking) in a QThread since i don't use callback functions.
libssh is a pure c library, so i'm looking for stderr, not std::cerr.
The platform is Linux.My research/approaches so far:
qInstallMessageHandler():
If understood correctly, it only works with qDebug(), qWarning()... thus useless.
Run the application in a QProcess:
At first i thought QProcess::readAllStandardError() was the solution, but apparently you can only run external programs in QProcess. I cannot run run my MainWindow Class from main.cpp as a QProcess, right? Because that would probably work, i think, otherwise it's infeasible.
I've read a few threads about redirecting stdout/stderr to a file, but i didn't find a way to read into a TextStream, and using a file as buffer is not feasible aswell.
Any ideas? Thanks in advance :)
Regards, Alex -
wrote on 10 Apr 2014, 15:33 last edited by
If libssh does not have any configuration option to redirect error log to a file or to a pipe you may try to do it yourself before making a call to libssh
You may use "freopen()":http://www.cplusplus.com/reference/cstdio/freopen/ or use "dup()":http://stackoverflow.com/a/956269 -
You can also redirect stderr through custom buffer:
@
char buffer[BUFSIZ];
setbuf(stderr, buffer);
@ -
wrote on 11 Apr 2014, 15:44 last edited by
Thanks for the answers! I tested Chris suggestion and i appeared to be working. However, i couldn't get it working in my program as i intended to. I will give you an update next week.
-
wrote on 17 Apr 2014, 08:58 last edited by
Ok, so i wrote a class wich uses setvbuf() to emit the libssh stderr output periodically as QString signal. This works perfect, for Linux, here is the code:
errorlogger.h
@#ifndef ERRORLOGGER_H
#define ERRORLOGGER_H#include <QObject>
#include <QTimer>
#include <QDebug>#include <iostream>
#include <stdio.h>#define BUFFERSIZE 655360
/*
- This class catches the stderr console output (from libssh) and emits it as signal.
- The stderr stream is buffered in errorBuffer. logErrors() checks the buffer periodically, invoked by a QTimer (every 500ms). If there is content available it is sent via the errorMessage signal to the gui.
*/
class ErrorLogger : public QObject
{
Q_OBJECT
public:
explicit ErrorLogger(QObject *parent = 0);
signals:
void errorMessage(QString message);public slots:
void logErrors();private:
char errorBuffer[BUFFERSIZE];
QTimer *timer;};
#endif // ERRORLOGGER_H
@errorlogger.cpp
@
#include "errorlogger.h"ErrorLogger::ErrorLogger(QObject *parent) :
QObject(parent)
{
// redirect stderr to errorBuffer
memset(errorBuffer, 0, sizeof(errorBuffer));
setvbuf(stderr, errorBuffer, _IOLBF, sizeof(errorBuffer));// set up QTimer to call logErrors periodically timer = new QTimer(this); timer->start(500); connect(timer, SIGNAL(timeout()), this, SLOT(logErrors()));
}
void ErrorLogger::logErrors()
{
fflush(stderr);// if there is stuff in the buffer, send it as errorMessage signal and clear the buffer if(strlen(errorBuffer) > 0){ emit errorMessage(errorBuffer); // send buffer content to gui memset(errorBuffer, 0, sizeof(errorBuffer)); }
}
@The thing is, i need this for Windows as well. Under Windows, it compiles without a warning, but it doesn't work properly. If i have something like fprintf(stderr, "test"); in my code, it is caught by the class, however, the whole output from libssh is not.
Does anyone have an idea why? Maybe because the libssh stuff runs in an extra thread? -
wrote on 19 Apr 2014, 16:14 last edited by
On Windows you need to be sure that your software and 3rd-party library use the same CRT library. If they don't then you will read nothing as every CRT version has separated std-objects instances. "Read this for more details":http://www.syndicateofideas.com/posts/fighting-the-msvcrt-dll-hell
-
wrote on 22 Apr 2014, 14:33 last edited by
Wow, that was the actual problem, thanks Bogdan! I used a precompiled libssh dll from the internet, which was apparently compiled with Visual Studio 2013. I then compiled my own version of libssh with Visual Studio 2012 (which is a huge pain btw) and it worked. The code is even platfrom independent.
Thanks you all for your support!P.s.: For anyone else ever encountering this problem: You can figure out with wich version of Visual Studio your dll has been compiled with the following way: Open the dll with the program Dependency Walker and watch out for msvcr1X0.dll
msvcr120.dll is VS 2013, msvcr110.dll is VS 2012.
2/7