Read () из файлового дескриптора зависает - PullRequest
0 голосов
/ 02 февраля 2010

Эй, надеюсь, это мой последний вопрос, связанный с PTY, и я могу перейти к более интересным вопросам. (С;

Вот набор небольших функций, которые я написал для создания и чтения / записи в pty: http://pastebin.com/m4fcee34d Единственная проблема заключается в том, что они не работают! После того, как я запустил инициализатор и writeToPty ("ls -l"), 'output' из readFromPty по-прежнему пуст.

Ubuntu, QT C ++

РЕДАКТИРОВАНИЕ: Хорошо, я могу подтвердить, что все это работает, кроме цикла чтения. На вкладке отладчиков 'locals / watchers' показано, что QString 'output' действительно получает правильные данные, помещенные в него, но после того, как в нем (read ()) заканчивается символ из выходных данных, которые он выполняет, а затем зависает. Что происходит и как я могу это исправить? Спасибо! (С:

#include <iostream>
#include <unistd.h>
#include <utmp.h>
#include <pty.h>

#include <QString>
#include <QThread>
// You also need libutil in your .pro file for this to compile.

class CMkPty
{
public:
    CMkPty( int *writeChannel, int *readChannel );
    ~CMkPty();
    int runInPty( char *command );
    int writeToPty( char *input );
    int readFromPty( QString output );
    int m_nPid;

private:
    int m_nMaster, m_nSlave, m_nPosition, m_nBytes;
    char *m_chName;
    void safe_print( char *s );
    char m_output;

};

CMkPty::CMkPty( int *masterFD, int *slaveFD )
{
    openpty( &m_nMaster, &m_nSlave, (char*)0, __null, __null );
    m_nPid = fork();
    *masterFD = m_nMaster;
    *slaveFD = m_nSlave;
    if( m_nPid == 0 )
    {
        login_tty( m_nSlave );
        execl( "/bin/bash", "-l", (char*)0 );
        return;
    }
    else if( m_nPid > 0 )
    {
        return;
    }
    else if( m_nPid < 0 )
    {
        std::cout << "Failed to fork." ;
        return;
    }
}
CMkPty::~CMkPty()
{
    close( m_nMaster );
    close( m_nSlave );
}
int CMkPty::writeToPty( char *szInput )
{
    int nWriteTest;
    write( m_nMaster, szInput, sizeof( szInput ) );
    nWriteTest = write( m_nMaster, "\n", 1 );
    if( nWriteTest < 0 )
    {
        std::cout << "Write to PTY failed" ;
        return -1;
    }
    return 0;
}
int CMkPty::readFromPty( QString output )
{
        char buffer[ 160 ];
        m_nBytes = sizeof( buffer );
        while ( ( m_nPosition = read( m_nMaster, buffer, m_nBytes ) ) > 0 )
        {
            buffer[ m_nPosition ] = 0;
            output += buffer;
        }
       return 0;
}

РЕДАКТИРОВАТЬ: Здесь это ссылка на вопрос с кодом, который, наконец, работал для меня.

1 Ответ

2 голосов
/ 07 февраля 2010

Я полностью знаком с posix, но после прочтения этой страницы http://pwet.fr/man/linux/fonctions_bibliotheques/posix/read у меня появилось некоторое понимание. Более того, я не вижу, как вы корректируете значение M_nBytes, если вы не прочитали столько, сколько ожидали на первом проходе цикла.

edit: по этой ссылке, возможно, это поможет:

Если в каком-то процессе канал открыт для записи, а O_NONBLOCK очищен, read () блокирует вызывающий поток до тех пор, пока не будут записаны некоторые данные, или канал не будет закрыт всеми процессами, у которых канал был открыт для записи.

При попытке чтения файла (кроме канала или FIFO), который поддерживает неблокирующее чтение и не имеет данных, доступных в данный момент:

* Если O_NONBLOCK очищен, read () блокирует вызывающий поток, пока некоторые данные не станут доступными.

по сути, если вы не находитесь в состоянии ошибки и говорите ему продолжать чтение, он будет блокироваться, пока не найдет что-то для чтения.

...