pclose() в файловом дескрипторе, открытом с помощью popen(), возвращает errno 10 (нет дочерних процессов)

Я использую Linux и пытаюсь сделать следующее:

  1. Запустите ls в текущем каталоге (используя popen)
  2. Вывести результат в буфер (используя fread из дескриптора канала)
  3. закрыть трубу (используя pclose).

Все работает нормально (буфер заполнен корректно результатом ls), но когда я проверяю результат pclose (), он возвращает -1, а errno устанавливается в 10 (нет дочерних процессов). Я понятия не имею, почему это происходит, но я не могу игнорировать это (если нет разумного объяснения, почему это происходит).

Мой код:

FILE * lsoutput = NULL;
lsoutput = popen("ls -ltr", "r");
if (readFromPipeOrFile(lsOutput, pSendBuf, pSendActualSize) == -1)
{
        printf("readFromPipeOrFile failed.");
        pclose(lsOutput);
        safeFree(pSendBuf);
        return -1;
}

if (pclose(lsOutput) == -1) // No idea why it returns -1 but it does...
{
        printf("pclose failed");
        printf("errno: %d\n", errno);
        printf("strerror: '%s'", strerror(errno));
        return -1;
}

Код для readFromPipeOrFile (функция записи в буфер):

int readFromPipeOrFile(FILE * pipeOrFile, char ** pSendBuf, size_t * pSendActualSize)
{
     int multiplication = 1;
     char * pSendBufCurrentLocation = NULL;
     ERR_RETURN(pipeOrFile == NULL || pSendBuf == NULL || pSendActualSize == NULL,
                     "No values should be NULL.");
     ERR_RETURN(*pSendBuf != NULL, "*pSendBuf should be NULL");

     *pSendBuf = (char *) calloc (MAX_READ_FROM_STREAM * multiplication, sizeof(char));
     ERR_RETURN(*pSendBuf == NULL, "Failed allocating sendBuf");

     pSendBufCurrentLocation = *pSendBuf;
     while (fread(pSendBufCurrentLocation, MAX_READ_FROM_STREAM, 1, pipeOrFile) == 1)
     {
             ++multiplication;
             *pSendBuf = realloc(*pSendBuf, MAX_READ_FROM_STREAM * multiplication);
             ERR_RETURN(*pSendBuf == NULL, "Failed re-allocating sendBuf");

             pSendBufCurrentLocation = *pSendBuf + (MAX_READ_FROM_STREAM * (multiplication - 1));
             memset(pSendBufCurrentLocation, '\0', MAX_READ_FROM_STREAM);
     }

     ERR_RETURN(!feof(pipeOrFile), "Hasn't reached eof but fread stopped");
     ERR_RETURN(ferror(pipeOrFile), "Error in fread");

     *pSendActualSize = MAX_READ_FROM_STREAM * multiplication;

     return 0;
}

Заранее спасибо! РЕДАКТИРОВАТЬ: ERR_RETURN это просто макрос, который проверяет, является ли условие для первого параметра истинным, и если это так, выведите строку во втором параметре и верните -1.

2 ответа

Сигнал (SIGCHLD, SIG_IGN) вызовет pclose(), в результате он вернет -1, а для errno будет установлено значение 10 (нет дочерних процессов).

Согласно документации для pclose(), это возвращает -1 если wait4 возвращает ошибку. Тем не менее, это ничего не говорит о настройке errno (кроме настройки ECHILD если он не смог получить статус ребенка), поэтому я не уверен, что вы можете рассчитывать на strerror() Строка является точной.

Подразумевается, что ls выход с кодом ошибки, который подразумевает, что ls возникли проблемы с доступом к подкаталогу (ошибка разрешения?). Итак, у вас есть результаты, потому что ls возвратил то, что он мог прочитать, но это неполное чтение, потому что он не мог получить доступ к подкаталогу в рекурсии.

Другие вопросы по тегам