#php #c #c #linux #centos
#php #c #c #linux #centos
Вопрос:
у меня есть приложение, написанное на C , которое использует opencv 2.0, curl и библиотеку opensurf. Сначала PHP-скрипт (cron.php ) вызывает proc_open и вызывает приложение C (называемое icomparer). По завершении обработки N изображений возвращаются группы с указанием одинаковых изображений, после чего скрипт использует:
shell_exec('php cron.php > /dev/null 2>amp;1 amp;');
die;
И запускается снова. Ну, после 800 или 900 итераций мой icomparer начинает ломаться. Система не позволяет мне создавать больше файлов в icomparer и в php-скрипте.
proc_open(): unable to create pipe Too many open files (2)
shell_exec(): Unable to execute 'php cron.php > /dev/null 2>amp;1 amp;'
И curl тоже терпит неудачу:
couldn't resolve host name (6)
Все выходит из строя. Я думаю, что я делаю что-то неправильно, например, я не знаю, освобождает ли запуск другого PHP-процесса из PHP-процесса ресурсы.
В «icomparer» я закрываю все открытые файлы. Возможно, не все мьютексы освобождаются с помощью mutex_destroy… но в каждом итераторе приложение c закрывается, я думаю, что все материалы выпущены правильно?
На что я должен обратить внимание? Я пробовал отслеживать открытые файлы с помощью stof.
- Php 5.2
- Centos 5.X
- 1 ГБ оперативной памяти
- жесткий диск объемом 120 ГБ (используется на 4%)
- 4 x intel xeon
- Является ли VPS (машина имеет 16 ГБ оперативной памяти)
- Процесс открывает 10 потоков и объединяет их.
Ответ №1:
Похоже, у вас произошла утечка файловых дескрипторов.
Комментарии:
1. Я использую ofstream и закрываю их с помощью «.close();».
2. Возможно, утечка дескрипторов из C произошла не из-за вас. Возможно, произошла утечка дескрипторов из PHP.
Ответ №2:
В Unix-подобных системах дочерние процессы наследуют дескрипторы открытых файлов родительского. Однако, когда дочерний процесс завершает работу, он закрывает все свои копии открытых файловых дескрипторов, но не родительские копии.
Таким образом, вы открываете файловые дескрипторы в родительском файле, а не закрываете их. Держу пари, что вы не закрываете каналы, возвращаемые proc_open()
вызовом.
И вам также нужно будет вызвать proc_close()
тоже.
Комментарии:
1. Мммммм, я открываю 3 канала, стандартный ввод «r», стандартный вывод «w» и ошибку «a» (указывая на этот последний на файл). Я использую его только для получения выходных данных приложения и ошибки при записи в файл. Я должен закрыть первое. Канал с ошибкой файла закрывается автоматически, верно? (Спасибо)
2. Не закрывая первый канал (stdin «r»), достаточно одного, чтобы сломать скрипт? Скрипт закрывается в каждом итераторе, я думаю, что PHP закрывает его автоматически.
3. @William: Есть ли другие файловые дескрипторы в другом месте, которые не закрываются. То есть, очевидно, что есть , иначе у вас не было бы нехватки. Вы только что исключили один потенциальный источник утечки.
Ответ №3:
Да, похоже, что вы открываете процессы, но не закрываете их после использования, и — как кажется — они не закрываются автоматически (что может сработать при некоторых обстоятельствах).
Убедитесь, что вы закрыли / завершили свой процесс с помощью proc_close($res)
, если вы больше не используете ресурс.
Комментарии:
1. Нет, я использую proc_close для получения выходных данных. Спасибо.
2. Как можно использовать proc_close() для получения выходных данных? O_o Как указано в руководстве по PHP:
int *exit_code* proc_close ( resource *$process* )
. Вы проверили код выхода, чтобы знать, что программа завершилась так, как вы ожидали?3. Извините, я получаю вывод с помощью канала stdout. Затем я закрываю с помощью proc_close и сохраняю возвращаемое значение: P
Ответ №4:
Ваше приложение не закрывает свои файлы / сокеты. Вы можете попробовать использовать системный вызов ulimit, с помощью которого вы можете уменьшить количество открытых файлов, разрешенных для каждого приложения. Взгляните: man ulimit
Комментарии:
1. Это только замаскировало бы проблему. @William Вам следует проверить наличие открытых дескрипторов и закрыть их все перед вызовом функции shell_exec.
2. Я предположил, что, когда я скажу, что вы не закрываете свои файлы / сокеты, кто-нибудь проверит это сам. 🙂 Возможно, он не может закрыть дескрипторы, потому что он все еще использует их.
3. 1 к @RedX. Если у вас произошла утечка файловых дескрипторов, ответ определенно не в том, чтобы игнорировать проблему.