Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Read stderr output from own process
QtWS25 Last Chance

Read stderr output from own process

Scheduled Pinned Locked Moved General and Desktop
7 Posts 4 Posters 4.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    AlexanderL
    wrote on 10 Apr 2014, 14:55 last edited by
    #1

    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

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andreyc
      wrote on 10 Apr 2014, 15:33 last edited by
      #2

      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

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on 10 Apr 2014, 22:28 last edited by
        #3

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

        1 Reply Last reply
        0
        • A Offline
          A Offline
          AlexanderL
          wrote on 11 Apr 2014, 15:44 last edited by
          #4

          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.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            AlexanderL
            wrote on 17 Apr 2014, 08:58 last edited by
            #5

            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?

            1 Reply Last reply
            0
            • B Offline
              B Offline
              bodzio131
              wrote on 19 Apr 2014, 16:14 last edited by
              #6

              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

              1 Reply Last reply
              0
              • A Offline
                A Offline
                AlexanderL
                wrote on 22 Apr 2014, 14:33 last edited by
                #7

                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.

                1 Reply Last reply
                0

                2/7

                10 Apr 2014, 15:33

                5 unread
                • Login

                • Login or register to search.
                2 out of 7
                • First post
                  2/7
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved