Read stderr output from own process



  • 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



  • 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


  • Moderators

    You can also redirect stderr through custom buffer:
    @
    char buffer[BUFSIZ];
    setbuf(stderr, buffer);
    @



  • 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.



  • 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?



  • 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



  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.