Ответ 1
Проблема с файлами PID многогранна, не ограничивается только переработкой и перезагрузкой.
Большая проблема заключается в том, что между информацией в файле PID и состоянием процесса существует неизбежное отключение/расхождение.
Это поток использования файлов PID:
- Вы используете fork и выполняете процесс. "Родительский" процесс знает PID вилки и имеет гарантии, что этот PID зарезервирован исключительно для его вилки.
- Ваш родитель записывает PID вилки в файл.
- Ваш родитель умирает вместе с ним и гарантирует эксклюзивность PID.
- Другой процесс считывает число в PID файле.
- Другой процесс проверяет, есть ли процесс в системе с тем же PID, что и тот, который он читал.
- Другой процесс отправляет сигнал процессу с прочитанным PID.
В (1) все прекрасно и денди. У нас есть PID, и ядро гарантирует, что это число зарезервировано для нашего предполагаемого процесса.
В (2) вы получаете контроль над PID для других процессов, которые не имеют этой гарантии. Сама по себе не проблема, но такой акт редко бывает когда-либо без ошибок.
В (3) ваш родительский процесс умирает. Только в нем была гарантия ядра на эксклюзивность PID. Он может или не мог сделать ожидание (2) на PID. Истинное состояние предполагаемого процесса теряется, все, что у нас осталось, - это идентификатор в PID файле, который может или не может ссылаться на предполагаемый процесс.
В (4) процесс без каких-либо гарантий считывает PID файл, любое использование этого числа имеет только произвольный успех.
В (5) процесс без каких-либо гарантий фактически использует идентификатор для чего-то, это первая точка, в которой мы действительно делаем что-то плохое: мы запрашиваем ядро с помощью идентификатора процесса, который может или не может ссылаться на предполагаемый процесс. Ответ, который мы вернем, будет касаться состояния процесса с этим PID, не обязательно нашего предполагаемого процесса.
В (6) мы совершаем худшую ошибку: мы на самом деле выполняем мутирующее действие, направленное на то, чтобы повлиять на начальный процесс, но никоим образом не гарантируя этого намерения. Мы могли бы сигнализировать о любом случайном системном процессе.
Почему это? Какого рода вещи могут случиться с PID?
В любом месте после (1) реальный процесс может умереть. Пока родитель сохраняет свою гарантию на эксклюзивность PID, ядро не будет перерабатывать PID. Он по-прежнему будет существовать и будет ссылаться на то, что раньше было вашим процессом (мы называем это "зомби" процессом, ваш реальный процесс умер, но PID по-прежнему зарезервирован для него в одиночку). Ни один другой процесс не может использовать этот PID и сигнализировать, что он вообще не достигнет какого-либо процесса.
Как только родитель освобождает свою гарантию или после (3), ядро перерабатывает PID мертвого процесса. Зомби ушел, и теперь PID теперь может использоваться любым другим новым процессом, который разветвляется. Скажем, вы компилируете что-то, тысячи мелких процессов порождаются. Ядро выбирает случайные или последовательные (в зависимости от его конфигурации) новые PID для каждого. Вы закончили, теперь вы перезапускаете apache. Ядро повторно использует освобожденный PID вашего мертвого процесса для чего-то важного.
PID файл все еще содержит PID. Любой процесс, который считывает PID файл (4), предполагает, что это число относится к вашему длительному процессу.
Любое действие (5) (6), которое вы берете с прочитанным вами номером, будет нацелено на новый процесс, а не на старый.
Не только это, но вы не можете выполнять никаких проверок до вашего действия, так как существует неизбежная гонка между любой проверкой, которую вы можете выполнить, и любыми действиями, которые вы можете выполнить. Если вы сначала посмотрите на ps
, чтобы узнать, что такое "имя" вашего процесса (не то, что это действительно потрясающая гарантия чего-либо, пожалуйста, не делайте этого), а затем сообщите об этом, время между вашим ps
проверьте, и ваш сигнал все еще мог видеть, как процесс умирает, и/или перерабатывается новым процессом. Корень из всех этих проблем заключается в том, что ядро не дает вам никаких эксклюзивных гарантий использования PID, поскольку вы не являетесь его родителем.
Мораль истории: НЕ ДАЙТЕ PID ваших детей кому-либо еще. Родитель и только родитель должны использовать его, потому что он единственный в системе (за исключением ядра) с любыми гарантиями на его существование и идентичность.
Обычно это означает, что родитель жив и вместо того, чтобы сигнализировать что-то, чтобы завершить процесс, вместо этого поговорить с родителем; с помощью гнезд или тому подобного. См. http://smarden.org/runit/ и др.