我在OS X上运行了一个旧的C ++应用程序(10.10 / Yosemite)。
当我调试应用程序时,我在以下代码行中得到一个例外:
// 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
为-1
。 errno
错误代码为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 ++ - pro,这里是必需的行代码。猜猜所有不需要的管道或者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;
答案 0 :(得分:2)
当您不再需要时,需要使用close
关闭管道FD。
答案 1 :(得分:2)
每个进程允许您拥有2560个打开文件,因此您应该在不再需要时关闭其他文件和/或管道。
当你完成资源时,发布资源总是很好的建议。