pclose() в файловом дескрипторе, открытом с помощью popen(), возвращает errno 10 (нет дочерних процессов)
Я использую Linux и пытаюсь сделать следующее:
- Запустите ls в текущем каталоге (используя popen)
- Вывести результат в буфер (используя fread из дескриптора канала)
- закрыть трубу (используя 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
возвратил то, что он мог прочитать, но это неполное чтение, потому что он не мог получить доступ к подкаталогу в рекурсии.