2015-02-09 19 views
1

我有一个旧的C++应用程序在OS X(10.10 /优胜美地)上运行。C++管道,太多打开的文件,Errno 25

当我调试我就在这下面的代码行的异常应用程序:

// create pipe 
    int pipefd[2]; 
    int piperet = pipe(pipefd); 
    if(piperet) 
    { 
     wcsncpy(errbuf, CEmpError::GetErrorText(CEmpError::ERR_SYSTEM, L"Can't create pipe for IPC.", errno).c_str(), errbuflen); 
     CEmpError::LogError(errbuf); 
     return CEmpError::ERR_SYSTEM; //= 115 
    } 

所以应用程序在运行,做这个代码行几次。过了一会儿pipette-1errno错误代码为25.

经过一番研究,这意味着“打开的文件过多”。是否有解决方法来关闭所有这些打开的文件?或者有可能知道哪些文件打开了太多?

当我输入端子ulimit -a我得到:

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
max locked memory  (kbytes, -l) unlimited 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 2560 
pipe size   (512 bytes, -p) 1 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 709 
virtual memory   (kbytes, -v) unlimited 

所以我不是超级C++ - 亲,这里需要的行代码。猜猜所有不需要的管道或pipefd将被关闭。

// create pipe 
    int pipefd[2]; 
    int piperet = pipe(pipefd); 
    if(piperet) 
    { 
     wcsncpy(errbuf, CEmpError::GetErrorText(CEmpError::ERR_SYSTEM, L"Can't create pipe for IPC.", errno).c_str(), errbuflen); 
     CEmpError::LogError(errbuf); 
     return CEmpError::ERR_SYSTEM; 
    } 

    CEmpError *pError = 0; 

    // after transfer the execution bit could be reset, so set the rights back 
    chmod(args[0], S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 

    pid_t pid = fork(); 
    if(pid == 0) 
    { // child process 

     close(pipefd[0]); // close reading end 
     int fd = pipefd[1]; 

     // redirect stdout and stderr to pipe 
    dup2(fd, STDOUT_FILENO); 
    dup2(fd, STDERR_FILENO); 

    close(fd); // not needed anymore 

     // execute steup.sh with built argument list 
     execvp(args[0], (char**)args); 

     // if we ever reached this line the exec failed and we need to report error to parent process 
     // once we are in child process we will print the error into stdout of our child process 
     // and parent process will parse and return it to the caller. 
     char buf[128]; 
     sprintf(buf, "setup.sh:ERROR:PI%03d",CEmpError::ERR_EXEC); 

     perror(buf); 

     // keep the process alive until the parent process got the error from the pipe and killed this child process 
     sleep(5); 

     return CEmpError::ERR_EXEC; 
    } 
    else if (pid > 0) 
    { // parent process 
     delete[] args[0]; // release memory allocated to f. 
     delete[] args[3]; // release memory allocated to log f. 
     delete[] args[5]; // release memory allocated to pn 
     close(pipefd[1]); 

     pParser = new CPackageInstallerParser(); 

     FILE* fp = fdopen(pipefd[0], "r"); 
     /*int res = */setvbuf(fp, NULL, _IOLBF, 0); 

     try 
     { 
      pParser->ParseOutput(fp, statusCallback, statusContext, logFileName); 
     } 
     catch (CEmpError* pErr) 
     { 
      if (pErr->ErrorCode == CEmpError::ERR_EXEC) 
       kill(pid, SIGABRT); // the error is parsed kill the child process 
      pError = pErr; 
     } 
     catch (...) 
     { 
      // some exception from statusCallback 
      fclose(fp); 
      delete pParser; 
      pParser = NULL; 
      throw; 
     } 

     fclose(fp); 

     int stat; 
     // wait for the installation process to end. 
     waitpid(pid, &stat, 0); 

     if (WIFEXITED(stat) && (stat % 256 == 0) && pError == NULL) 
     { 
      // exited normally with code 0 (success) 
      // printf("Installed succesfully!\n"); 

      // register succesful operation result 
      try 
      { 
       RegisterResult(operation); 
      } 
      catch (CEmpError* pErr) 
      { 
       pError = pErr; 
      } 
     } 
     else 
     { 
      if (pError == NULL) // no error was caught by parser 
       pError = new CEmpError(CEmpError::ERR_UNKNOWN); 
      //dumpError(stat); 
     } 
    } 
    else 
     pError = new CEmpError(CEmpError::ERR_FORK); 


    //clean up and exit 
    if (pParser != NULL) 
     delete pParser; 
    pParser = NULL; 

    int exitcode = 0; 
    if (pError != NULL) 
    { 
     exitcode = pError->ErrorCode; 
     wcsncpy(errbuf, pError->GetErrorText().c_str(), errbuflen); 
     pError->Log(); 
     delete pError; 
    } 
    return exitcode; 

回答

2

当您不再需要管道FD时,需要使用close关闭管道FD。

+0

uao。混合C错误与C++异常!看起来很糟糕 – GameDeveloper 2015-02-09 16:01:19

2

您可以在每个进程中打开2560个文件,因此在不再需要时应关闭其他文件和/或管道。

当你完成它们的时候,释放资源总是很好的建议。

+0

我认为“软限制”是2560,而“硬限制”是无限的“ulimit -Sn”和“ulimit -Hn”告诉我这一点。 – 2015-02-09 15:54:03

+0

无论是软限还是硬限,似乎都会打开大量文件。所以在任何情况下,都要小心所消耗的资源。 – 2015-02-09 15:59:16

相关问题