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

Using QIODevice with anonymous pipes



  • I want to use a QIODevice in order to read from a unnamed pipe if data is available.
    I tried this with QFile:

    m_pFile_Pipe = new QFile();
    HANDLE hRead, hWrite;
    connect(m_pFile_Pipe, SIGNAL(readyRead()), this, SLOT(OutputAvailable_QFile()));
    
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    
    CreatePipe(&hRead, &hWrite, &sa, 0);
    auto fhRead = _open_osfhandle((intptr_t)hRead, _O_RDONLY);
    auto OpenResult = m_pFile_Pipe->open(fhRead, QIODevice::ReadOnly);
    

    The "raw" pipe itself works, I can read data from it.
    However, readyRead() is never signaled and during testing:

    void TestPipe() {
        char acBuffer[128];
        DWORD NumBytesRead;
        
        auto NumBytes = m_pFile_Pipe->bytesAvailable();
        qDebug() << "NumBytes" << NumBytes;
        ReadFile(hRead, acBuffer, sizeof(acBuffer), &NumBytesRead, NULL);
        qDebug() << QString::fromUtf8(acBuffer);
        while (m_pFile_Pipe->canReadLine()) {
            auto out = m_pFile_Pipe->readLine(512);
            qDebug() << "Line: " << out;
        }
        auto out_all = m_pFile_Pipe->readAll();
        qDebug() << "Raw: " << out_all;
    }
    

    NumBytes was always 0, canReadLine() always returned false, and readAll() did not return.
    ReadFile() could read the expected data.

    Is there a QOIDevice to use for anonymous pipes?


  • Moderators

    @Sweepi said in Using QIODevice with anonymous pipes:

    Is there a QOIDevice to use for anonymous pipes?

    I don't believe so. Probably cleanest is to implement your own QIODevice. However there are questions about the code you posted.

    For one what is OpenResult's value? I wouldn't expect the file to be opened multiple times successfully.
    And secondly, in your test code you don't spin the event loop so I see no reason to expect any signals to be emitted from the QFile.
    And lastly, QFile is a random access device, while a pipe is not, so weird behavior isn't unexpected.



  • @kshegunov

    OpenResult was always true.
    However, since you mentioned that QFile and the pipe handle is a mismatch, I guess this does not mean too much.

    I stripped the code (in the starting post) down a little bit (since it contained unrelated "noise"), the event loop was working in my actual code, e.g. TestPipe() was called from a timer.

    Probably cleanest is to implement your own QIODevice.

    Can you point me to sth. similar where I can get ideas?
    E.g. I have no concept of how I would know that there is data available but to "poll" the pipe, which seems wrong.

    And lastly, QFile is a random access device, while a pipe is not, so weird behavior isn't unexpected.

    Actually, I have a follow-up question for this one:
    stderr etc. are also sequential devices, aren't they?
    I am wondering, because I remember an Qt example to open stderr using QFile.


  • Moderators

    @Sweepi said in Using QIODevice with anonymous pipes:

    Can you point me to sth. similar where I can get ideas?

    Any of the socket classes, or QProcess's stream reading/writing should be sufficient to get you started. For example, take a look here https://code.woboq.org/qt5/qtbase/src/corelib/io/qprocess.cpp.html#_ZN15QProcessPrivate18tryReadFromChannelEPNS_7ChannelE

    E.g. I have no concept of how I would know that there is data available but to "poll" the pipe, which seems wrong.

    You should try with QSocketNotifier.

    stderr etc. are also a sequential devices, aren't they?

    Yes.

    I am wondering, because I remember an Qt example to open stderr using QFile.

    Maybe, I don't know which example you mean. I open the standard streams through QTextStream directly, like this:

    QTextStream out(stdout);
    

    However I haven't checked what's the underlying code. Maybe you could check that too, I'd be interested to know as well.



  • @kshegunov

    Maybe, I don't know which example you mean.

    Found it:
    https://doc.qt.io/qt-5/qfile.html#open-1

    But maybe this is different since stderr is opened with QIODevice::WriteOnly, so there is no random access possible anyway.

    Thanks for all the hints, going to dig through this now!


Log in to reply