C ++ Pipe, слишком много открытых файлов, Errno 25

У меня есть старое приложение C ++, работающее на OS X (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;

1

Решение

Вы должны закрыть трубы FD с close когда они вам больше не нужны.

2

Другие решения

Вам разрешено иметь 2560 открытых файлов на процесс, поэтому вы должны закрывать другие файлы и / или каналы, когда они больше не нужны.

Это всегда хороший совет, чтобы освободить ресурсы, когда вы закончите с ними.

2

По вопросам рекламы [email protected]