2015-02-09 18 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

相關問題