用popen()打开的文件描述符上的pclose()返回errno 10(没有子进程)

时间:2013-04-13 21:11:01

标签: c linux popen fread pclose

我正在运行linux,我尝试执行以下操作:

  1. 在当前目录上运行ls(使用popen)
  2. 将结果输出到缓冲区(使用来自管道描述符的fread)
  3. 关闭管道(使用pclose)。
  4. 一切正常(缓冲区使用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 个答案:

答案 0 :(得分:0)

根据pclose()的文档,如果-1返回错误,则返回wait4。但是,它没有说明设置errno(除了设置ECHILD,如果它无法获得子状态),所以我不确定你可以指望strerror()字符串是准确。

暗示ls退出时会显示错误代码,这意味着ls无法访问子目录(权限错误?)。因此,您有结果,因为ls返回了它可以读取的内容,但它是一个不完整的读取,因为它无法访问递归中的子目录。

答案 1 :(得分:0)

信号(SIGCHLD,SIG_IGN) 将导致pclose()结果返回-1并且errno设置为10(无子进程)。