Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Fri, Nov 24, 2017 at 01:12:46AM +0200, Gena Makhomed wrote:

> On 23.11.2017 23:00, Maxim Dounin wrote:
> 
> >>> Это всё замечательно (за вычетом того, предлагаемое использование
> >>> daemon(3) почему-то не учитывает, что после вызова daemon(3)
> >>> parent-процесса уже нет, а "ошибка" - не ошибка), но не отменяет
> >>> того, что чуть менее, чем все существующие демоны делают именно
> >>> "daemon(); write_pidfile();", и при таком подходе - ситуацию не
> >>> изменить.
> 
> >> А при каком подходе ситуацию c nginx изменить можно?
> >> Если говорить конструктивно.
> 
> > Чтобы изменить ситуацию конкретно с nginx - нужно сесть и сделать
> > хороший патч.  Очевидно, это сделать можно, и даже не очень
> > сложно.  Я, как уже неоднократно сказал, не возражаю.
> 
> Для меня это будет слишком сложный патч, в разумные сроки не напишу.
> 
> > Но сама идея, что все должны сесть и заняться выпиливанием
> > стандартного паттерна, который работал десятки лет, и делать
> > вместо это что-то своё с синхронизацией - не взлетит.
> 
> Эта идея уже взлетела. Если демон состоит из одного процесса
> - systemd может однозначно узнать его pid, проблемы могут возникать
> только с теми демонами, которые состоят из нескольких процессов.
> Из известных мне сервисов состоящих из более чем одного процесса:
> 
> * postfix - сделали синхронизацию и проблем с systemd больше нет.
> * httpd - перевели на Type=notify и проблем с systemd больше нет.
> * php-fpm - перевели на Type=notify и проблем с systemd больше нет.
> * nginx - только с этим сервисом наблюдаются проблемы под systemd.

Давайте, всё-таки, опеределимся: мы за всё хорошее против всего 
плохого (== чтобы демоны писали pid-файлы до выхода запущенного 
процесса, потому что по другому - плохо), или вопрос исключительно 
в том, чтобы systemd не ругался в логи?

Если за всё хорошее - то проблема, очевидно, не ограничевается 
сервисами из более чем одного процесса, и не решается переводом на 
Type=notify.  Она вообще ортогональна существованию systemd.  И 
идея её решения, очевидно, не взлетела, и уже наверное не взлетит.

Если чтобы systemd не ругался - то проблема, очевидно, не в том, 
чтобы сделать хорошо, а в том, убрать конкретную ругань (которая 
не несёт практического смысла, см. ниже).  И предолженный ранее 
workaround про sleep 0.1 - вполне себе в этом ключе же решение?

> >> О каких именно "чуть менее, чем все существующие демоны"
> >> сервисах Вы говорите? Есть еще кроме nginx примеры некорректного
> >> поведения systemd-сервисов с Type=forking которые запускают много
> >> дочерних процессов как это делает nginx или postfix?
> 
> > Не вижу причин, почему демоны с "много дочерних процессов" должны
> > отличаться от сервисов с "мало дочерних процессов".
> 
> systemd однозначно определяет pid демонов состоящих из одного процесса
> и поэтому для них в юнит-файле можно вообще не указывать опцию PIDFile=
> - все будет работать как надо даже если они стартуют без синхронизации.
> 
> Вот что говорит Lennart Poettering из Red Hat:
> 
> If you use Type=forking, then you'll get away with not specifiying a
> PID file in most cases, but it's racy as soon as you have more than
> one daemon process, and nginx appears to be one of this kind, hence
> please specify PIDFile=.
> 
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039833.html

Ну вот я посмотрел на это место чуть подробнее, и имею сказать, 
что это не совсем соответствует действительности.  Единственное, 
для чего нужен PIDFile в случае nginx'а - это чтобы systemd 
нормально реагировал на binary upgrade.

Для правильного детектирования основного процесса при запуске 
PIDFile не нужен, так как master-процесс - единственный, у кого 
parent'ом systemd, у остальных процессов parent'ом будет master.  
И соответственно все остальные процессы успешно отфильтрует вот 
этот код,
https://github.com/systemd/systemd/blob/master/src/core/cgroup.c#L1727:

/* Ignore processes that aren't our kids */
if (get_process_ppid(npid, ) >= 0 && ppid != mypid)
continue;

Однако если PIDFile не указывать, то "service nginx upgrade" 
приведёт к тому, что после выхода старого мастера systemd будет 
считать, что nginx умер, и убьёт все новые процессы.  Поэтому 
PIDFile указывать таки надо.

Соответственно имеем то что имеем: PIDFile указывать надо, от 
этого на старте могут появляться сообщения про "PID file not ... yet?".  
Сообщения эти безвредные, и ни на что не влияют, кроме собственно 
появления самих сообщений.

Если идти по пути синхронизации через pipe, то патч получается 
как-то такой.  Не могу сказать, что он мне нравится, особенно в 
контексте решения задачи "чтобы у systemd в логе стало на одну 
строчку меньше".

diff -r 325b3042edd6 src/core/nginx.c
--- a/src/core/nginx.c  Thu Nov 23 16:33:40 2017 +0300
+++ b/src/core/nginx.c  Fri Nov 24 07:07:44 2017 +0300
@@ -361,6 +361,10 @@
 return 1;
 }
 
+if (ngx_daemon_sync(cycle->log) != NGX_OK) {
+

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 23.11.2017 23:00, Maxim Dounin wrote:


Это всё замечательно (за вычетом того, предлагаемое использование
daemon(3) почему-то не учитывает, что после вызова daemon(3)
parent-процесса уже нет, а "ошибка" - не ошибка), но не отменяет
того, что чуть менее, чем все существующие демоны делают именно
"daemon(); write_pidfile();", и при таком подходе - ситуацию не
изменить.



А при каком подходе ситуацию c nginx изменить можно?
Если говорить конструктивно.



Чтобы изменить ситуацию конкретно с nginx - нужно сесть и сделать
хороший патч.  Очевидно, это сделать можно, и даже не очень
сложно.  Я, как уже неоднократно сказал, не возражаю.


Для меня это будет слишком сложный патч, в разумные сроки не напишу.


Но сама идея, что все должны сесть и заняться выпиливанием
стандартного паттерна, который работал десятки лет, и делать
вместо это что-то своё с синхронизацией - не взлетит.


Эта идея уже взлетела. Если демон состоит из одного процесса
- systemd может однозначно узнать его pid, проблемы могут возникать
только с теми демонами, которые состоят из нескольких процессов.
Из известных мне сервисов состоящих из более чем одного процесса:

* postfix - сделали синхронизацию и проблем с systemd больше нет.
* httpd - перевели на Type=notify и проблем с systemd больше нет.
* php-fpm - перевели на Type=notify и проблем с systemd больше нет.
* nginx - только с этим сервисом наблюдаются проблемы под systemd.


О каких именно "чуть менее, чем все существующие демоны"
сервисах Вы говорите? Есть еще кроме nginx примеры некорректного
поведения systemd-сервисов с Type=forking которые запускают много
дочерних процессов как это делает nginx или postfix?



Не вижу причин, почему демоны с "много дочерних процессов" должны
отличаться от сервисов с "мало дочерних процессов".


systemd однозначно определяет pid демонов состоящих из одного процесса
и поэтому для них в юнит-файле можно вообще не указывать опцию PIDFile=
- все будет работать как надо даже если они стартуют без синхронизации.

Вот что говорит Lennart Poettering из Red Hat:

If you use Type=forking, then you'll get away with not specifiying a
PID file in most cases, but it's racy as soon as you have more than
one daemon process, and nginx appears to be one of this kind, hence
please specify PIDFile=.

https://lists.freedesktop.org/archives/systemd-devel/2017-November/039833.html

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 23, 2017 at 09:00:07PM +0200, Gena Makhomed wrote:

> On 23.11.2017 19:13, Maxim Dounin wrote:
> 
>  В systemd's daemon(7) manpage очень подробно расписано
>  как должны вести себя SysV Daemons при работе с systemd.
>  И очевидно, что nginx этим требованиям не соответствует.
> 
>  Original process должен вызывать exit() только после того,
>  как будет полностью завершена инициализация daemon process,
>  в частности, после того как daemon process создаст свой pid файл.
> 
> >>> Это, что называется, всё очень интересно, но вызывает сомнение
> >>> успех подобных рекомендаций.  Особенно с учётом отсутствия
> >>> каких-либо внятных примеров того, что же использовать вместо
> >>> daemon(3).  О чём я, собственно, и писал выше.
> 
> >> Что использовать вместо daemon(3) документировано в daemon(7):
> >> https://www.freedesktop.org/software/systemd/man/daemon.html
> 
> >> Lennart Poettering очень подробно ответил на этот вопрос в рассылке:
> >> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039830.html
> 
> >> Впрочем, если очень хочется использовать все-таки daemon(3) то можно:
> >> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039834.html
> 
> >> Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
> >> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html
> 
> > Это всё замечательно (за вычетом того, предлагаемое использование
> > daemon(3) почему-то не учитывает, что после вызова daemon(3)
> > parent-процесса уже нет, а "ошибка" - не ошибка), но не отменяет
> > того, что чуть менее, чем все существующие демоны делают именно
> > "daemon(); write_pidfile();", и при таком подходе - ситуацию не
> > изменить.
> 
> А при каком подходе ситуацию c nginx изменить можно?
> Если говорить конструктивно.

Чтобы изменить ситуацию конкретно с nginx - нужно сесть и сделать 
хороший патч.  Очевидно, это сделать можно, и даже не очень 
сложно.  Я, как уже неоднократно сказал, не возражаю.

Но сама идея, что все должны сесть и заняться выпиливанием 
стандартного паттерна, который работал десятки лет, и делать 
вместо это что-то своё с синхронизацией - не взлетит.

> Посмотрел у себя в системе, CentOS 7.4 - там достаточно мало осталось
> сервисов Type=forking. Postfix например, запускает много процессов,
> как и nginx - проверил его исходники, он действует точно так,
> как рекомендуется в документе systemd's daemon(7) manpage.
> 
> О каких именно "чуть менее, чем все существующие демоны"
> сервисах Вы говорите? Есть еще кроме nginx примеры некорректного
> поведения systemd-сервисов с Type=forking которые запускают много
> дочерних процессов как это делает nginx или postfix?

Не вижу причин, почему демоны с "много дочерних процессов" должны 
отличаться от сервисов с "мало дочерних процессов".

In no particular order,

- memcached, делает deamonize() (который суть daemon(3) и 
  завершает исходный процесс), после чего пишет pid-файл.

https://github.com/memcached/memcached/blob/master/memcached.c#L6788
https://github.com/memcached/memcached/blob/master/memcached.c#L6924

- httpd, делает apr_proc_detach() (который суть daemon(3) и тоже 
  завершает исходный процесс) в worker_pre_config(), и сильно 
  после пишет pid-файл (в worker_run()).

https://github.com/apache/httpd/blob/trunk/server/mpm/worker/worker.c#L2002
https://github.com/apache/httpd/blob/trunk/server/mpm/worker/worker.c#L1663

- Reference-реализация PEP 3143 - Standard daemon process library, 
  https://www.python.org/dev/peps/pep-3143/, зовётся функция 
  detach_process_context() (которая в свою очередь зовёт функцию с 
  говорящим названием fork_then_exit_parent()), потом пишется 
  pid-файл.

https://pagure.io/python-daemon/blob/master/f/daemon/daemon.py#_376
https://pagure.io/python-daemon/blob/master/f/daemon/daemon.py#_389

- nptd, в отсутствии опции --wait-sync (которая суть замена 
  ntpdate) выходит сразу после fork(), pid-файл пишется позже в 
  рамках getconfig().

https://github.com/ntp-project/ntp/blob/stable/ntpd/ntpd.c#L730
https://github.com/ntp-project/ntp/blob/stable/ntpd/ntpd.c#L892

Тысячи их.

[...]

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Konstantin Pavlov
Здравствуйте, Илья,

On 23/11/2017 21:30, Илья Шипицин wrote:
> не совсем про systemd, скорее про пакеты
> 
> не пробовали вот такие хуки 
> https://fedoraproject.org/wiki/Packaging:Scriptlets#Systemd ?
> (для pre, post скриптов)

Мы собираем пакеты не только под systemd-enabled дистрибутивы из одних и тех же 
исходных пакетов, поэтому использовали уже раскрытые версии в соответствущих 
местах (см. http://hg.nginx.org/pkg-oss/file/tip/rpm/SPECS/nginx.spec.in#l238).

-- 
Konstantin Pavlov
www.nginx.com
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Evgeniy Berdnikov
On Wed, Nov 22, 2017 at 08:43:14PM +0300, Maxim Dounin wrote:
> С точки зрения практики - паттерн "daemon(); write_pidfile();" 
> используется чуть менее, чем везде, вплоть до соответствующих 
> библиотечных функций.  Так что инициатива выглядит, скажем так, 
> сомнительной.

 Отговорка, скажем так, неубедительная. Есть масса рискованных
 и ненадёжных паттернов поведения, но зачем им следовать, если
 можно сделать всё правильно, и это достаточно просто?
 Например, возможен такой вариант:

 1. Папа выполняет pipe(2) и форкает дочку.
 
 2. Дочка читает конфиги, открывает сокеты и делает все нужные
предварительные проверки, если всё ок -- пишет в пайп
свой pid и закрывает пайп, если нет -- делает exit().

 3. Прочитав пайп, папа видит смотрит, вернулся ли pid или
eof/ошибка. Если прочитан правильный pid, то он записывается
в файл, и папа делает exit(0), если нет, то дочка подбирается
waitpid()ом и её статус выбрасывается через exit() наверх.

 В идеале можно (и я бы сказал нужно) перед чтением пайпа поставить
 на него select() с таймером, чтобы задать максимальное время
 на запуск подпроцесса.

> Проще всего, IMHO, это было бы заткнуть на уровне systemd, 
> дожидаясь появления pid-файла при необходимости.

 Лучше делать не "как проще", а правильно.
-- 
 Eugene Berdnikov
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 23.11.2017 19:13, Maxim Dounin wrote:


В systemd's daemon(7) manpage очень подробно расписано
как должны вести себя SysV Daemons при работе с systemd.
И очевидно, что nginx этим требованиям не соответствует.



Original process должен вызывать exit() только после того,
как будет полностью завершена инициализация daemon process,
в частности, после того как daemon process создаст свой pid файл.



Это, что называется, всё очень интересно, но вызывает сомнение
успех подобных рекомендаций.  Особенно с учётом отсутствия
каких-либо внятных примеров того, что же использовать вместо
daemon(3).  О чём я, собственно, и писал выше.



Что использовать вместо daemon(3) документировано в daemon(7):
https://www.freedesktop.org/software/systemd/man/daemon.html



Lennart Poettering очень подробно ответил на этот вопрос в рассылке:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039830.html



Впрочем, если очень хочется использовать все-таки daemon(3) то можно:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039834.html



Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html



Это всё замечательно (за вычетом того, предлагаемое использование
daemon(3) почему-то не учитывает, что после вызова daemon(3)
parent-процесса уже нет, а "ошибка" - не ошибка), но не отменяет
того, что чуть менее, чем все существующие демоны делают именно
"daemon(); write_pidfile();", и при таком подходе - ситуацию не
изменить.


А при каком подходе ситуацию c nginx изменить можно?
Если говорить конструктивно.

Посмотрел у себя в системе, CentOS 7.4 - там достаточно мало осталось
сервисов Type=forking. Postfix например, запускает много процессов,
как и nginx - проверил его исходники, он действует точно так,
как рекомендуется в документе systemd's daemon(7) manpage.

О каких именно "чуть менее, чем все существующие демоны"
сервисах Вы говорите? Есть еще кроме nginx примеры некорректного
поведения systemd-сервисов с Type=forking которые запускают много
дочерних процессов как это делает nginx или postfix?

Проблемы в работе под управлением systemd сейчас есть только у nginx:
systemd: PID file /var/run/nginx.pid not readable (yet?) after start.
Все остальные сервисы у меня на серверах под systemd работают нормально.

Когда я спросил у Lennart Poettering насчет того,
что все существующие демоны так делают он мне ответил
"the better written ones synchronize properly".

Хочется чтобы и nginx тоже попадал в эту категорию "better written".

Когда я спрашивал разработчиков systemd чтобы они исправили
systemd, вот что Lennart Poettering из Red Hat мне ответил:

https://lists.freedesktop.org/archives/systemd-devel/2017-November/039834.html

[...]

>>> But "daemon(); write_pidfile();" is common pattern
>>> used by many services and even in library functions.

>> It may be common, but not necessarily correct. The parent process should
>> only exit *after* finishing all the preparations (i.e. something like
>> "fork(); write_pidfile(); exit()"), since systemd uses the exit as a 
signal

>> that the daemon is now "ready".

> You are joking? Why you think that this pattern is not correct?

It doesn't work on SysV init either: "/etc/init.d/nginx start ;
/etc/init.d/nginx stop" is racy as it will leave ngnx running if it the
PID file isn't written by the time the stop command is used.

[...]

> Or may be it will be simpler to fix root cause of problem in systemd?

Well, I wish you good luck fixing SysV init scripts too. Before we
talk about "fixing systemd", let's talk how do you intend to make
"/etc/init.d/nginx start ; /etc/init.d/nginx stop" work correctly,
without races, without sometimes leaving nginx running, if you don't
wait for the PID file to be written safely before exiting.

Lennart

--
Lennart Poettering, Red Hat

=

Что ему ответить? Как сделать так, чтобы команда
"/etc/init.d/nginx start ; /etc/init.d/nginx stop"
работала без глюков на CentOS 6 ? Она ведь глючит.

Может быть действительно имеет смысл сделать
"wait for the PID file to be written safely before exiting"
и не брать для nginx пример с кривых и глючных демонов
у которых есть race conditions при старте/остановке?


Максим, можно ли сделать так, чтобы nginx соответствовал
тем требованиям которые предъявляет systemd к SysV Daemons?



https://www.freedesktop.org/software/systemd/man/daemon.html



Можно, я ж разве против?


А как это лучше всего сделать?

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Илья Шипицин
23 ноября 2017 г., 22:55 пользователь Maxim Dounin 
написал:

> Hello!
>
> On Thu, Nov 23, 2017 at 12:30:45PM -0500, S.A.N wrote:
>
> > > С точки зрения практики - паттерн "daemon(); write_pidfile();"
> > > используется чуть менее, чем везде, вплоть до соответствующих
> > > библиотечных функций.  Так что инициатива выглядит, скажем так,
> > > сомнительной.
> > >
> > > Проще всего, IMHO, это было бы заткнуть на уровне systemd,
> > > дожидаясь появления pid-файла при необходимости.
> >
> > Возможно я чего-то не понимаю, но для Systemd лучше вообще не указывать
> pid
> > файл, вместо Type=fork использовать Type=notify, это более гибкий вариант
> > сообщить Systemd что процесс готов к работе.
> >
> > Вот подробней, кстати PostgreSQL и PHP-FPM уже перешли на него.
> > https://www.freedesktop.org/software/systemd/man/systemd.
> service.html#Type=
>
> Нет, спасибо, собираться с systemd'шными библиотеками - это не к
> нам.
>
>
не совсем про systemd, скорее про пакеты

не пробовали вот такие хуки
https://fedoraproject.org/wiki/Packaging:Scriptlets#Systemd ?
(для pre, post скриптов)


> --
> Maxim Dounin
> http://mdounin.ru/
> ___
> nginx-ru mailing list
> nginx-ru@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-ru
>
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 23, 2017 at 12:30:45PM -0500, S.A.N wrote:

> > С точки зрения практики - паттерн "daemon(); write_pidfile();" 
> > используется чуть менее, чем везде, вплоть до соответствующих 
> > библиотечных функций.  Так что инициатива выглядит, скажем так, 
> > сомнительной.
> > 
> > Проще всего, IMHO, это было бы заткнуть на уровне systemd, 
> > дожидаясь появления pid-файла при необходимости.
> 
> Возможно я чего-то не понимаю, но для Systemd лучше вообще не указывать pid
> файл, вместо Type=fork использовать Type=notify, это более гибкий вариант
> сообщить Systemd что процесс готов к работе.
> 
> Вот подробней, кстати PostgreSQL и PHP-FPM уже перешли на него.
> https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=

Нет, спасибо, собираться с systemd'шными библиотеками - это не к 
нам.

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 23.11.2017 19:30, S.A.N wrote:


для Systemd лучше вообще не указывать pid файл


Не лучше. Если Type=forking то pid файл необходимо указывать всегда:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039831.html


вместо Type=fork использовать Type=notify, это более гибкий вариант
сообщить Systemd что процесс готов к работе.


Тогда не будет работать обновление исполняемого файла на лету:
http://nginx.org/ru/docs/control.html#upgrade

# service nginx upgrade
Starting new master nginx: [  OK  ]
Graceful shutdown of old nginx:[  OK  ]

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 23.11.2017 18:44, Igor Sysoev wrote:


Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html



Интересно, откуда он это придумал про двойной fork()?


Скорее всего из книжки Richard W. Stevens
Advanced Programming in the UNIX Environment, 3rd Edition
https://www.amazon.com/Advanced-Programming-UNIX-Environment-3rd/dp/0321637739

Подробный ответ на stackoverflow с объяснением зачем двойной форк:
https://stackoverflow.com/a/31485256

Кстати, сама эта книжка
Advanced Programming in the UNIX Environment, 3rd Edition
в PDF формате на английском доступна для скачивания в интернете:
http://www.codeman.net/wp-content/uploads/2014/04/APUE-3rd.pdf
https://github.com/shihyu/Linux_Programming/blob/master/books/Advanced.Programming.in.the.UNIX.Environment.3rd.Edition.0321637739.pdf

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность S.A.N
> С точки зрения практики - паттерн "daemon(); write_pidfile();" 
> используется чуть менее, чем везде, вплоть до соответствующих 
> библиотечных функций.  Так что инициатива выглядит, скажем так, 
> сомнительной.
> 
> Проще всего, IMHO, это было бы заткнуть на уровне systemd, 
> дожидаясь появления pid-файла при необходимости.

Возможно я чего-то не понимаю, но для Systemd лучше вообще не указывать pid
файл, вместо Type=fork использовать Type=notify, это более гибкий вариант
сообщить Systemd что процесс готов к работе.

Вот подробней, кстати PostgreSQL и PHP-FPM уже перешли на него.
https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=

Posted at Nginx Forum: 
https://forum.nginx.org/read.php?21,277438,277473#msg-277473

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 23, 2017 at 07:44:57PM +0300, Igor Sysoev wrote:

> > On 23 Nov 2017, at 19:28, Gena Makhomed  wrote:
> > 
> > Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
> > https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html
> 
> Интересно, откуда он это придумал про двойной fork()?
> 
> Во FreeBSD используется только один fork() что в 2017 году:
> https://svnweb.freebsd.org/base/head/lib/libc/gen/daemon.c?revision=326025=co
> что в 1994:
> https://svnweb.freebsd.org/base/head/lib/libc/gen/daemon.c?revision=1573=co

Двойной форк нужен на Линуксе, чтобы случайно не получить себе 
обратно controlling terminal.  Документировано, например, тут в 
man daemon(3) у glibc, 
http://man7.org/linux/man-pages/man3/daemon.3.html:

   The GNU C library implementation of this function was taken from BSD,
   and does not employ the double-fork technique (i.e., fork(2),
   setsid(2), fork(2)) that is necessary to ensure that the resulting
   daemon process is not a session leader.  Instead, the resulting
   daemon is a session leader.  On systems that follow System V
   semantics (e.g., Linux), this means that if the daemon opens a
   terminal that is not already a controlling terminal for another
   session, then that terminal will inadvertently become the controlling
   terminal for the daemon.

Смысла это делать в nginx'е - скорее нет, IMHO.

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 23, 2017 at 06:28:55PM +0200, Gena Makhomed wrote:

> On 23.11.2017 17:37, Maxim Dounin wrote:
> 
> >> В systemd's daemon(7) manpage очень подробно расписано
> >> как должны вести себя SysV Daemons при работе с systemd.
> >> И очевидно, что nginx этим требованиям не соответствует.
> 
> >> Original process должен вызывать exit() только после того,
> >> как будет полностью завершена инициализация daemon process,
> >> в частности, после того как daemon process создаст свой pid файл.
> 
> > Это, что называется, всё очень интересно, но вызывает сомнение
> > успех подобных рекомендаций.  Особенно с учётом отсутствия
> > каких-либо внятных примеров того, что же использовать вместо
> > daemon(3).  О чём я, собственно, и писал выше.
> 
> Что использовать вместо daemon(3) документировано в daemon(7):
> https://www.freedesktop.org/software/systemd/man/daemon.html
> 
> Lennart Poettering очень подробно ответил на этот вопрос в рассылке:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039830.html
> 
> Впрочем, если очень хочется использовать все-таки daemon(3) то можно:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039834.html
> 
> Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html

Это всё замечательно (за вычетом того, предлагаемое использование 
daemon(3) почему-то не учитывает, что после вызова daemon(3) 
parent-процесса уже нет, а "ошибка" - не ошибка), но не отменяет 
того, что чуть менее, чем все существующие демоны делают именно 
"daemon(); write_pidfile();", и при таком подходе - ситуацию не 
изменить.

> > Впрочем, если верить ответу тут:
> > https://lists.freedesktop.org/archives/systemd-devel/2017-November/039825.html
> 
> > то соответствующее сообщение можно смело игнорировать, и systemd
> > на самом деле умеет дожидаться создания pid-файла.  То есть вопрос
> > лишь в том, что при этом systemd пишет в лог.
> 
> Не надо верить тому, что говорит Michael Chapman - он ошибается.
> systemd не ждет появления pid-файла, я это проверял по исходникам.
> 
> Лучше верить тому, что говорит Lennart Poettering, автор systemd:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039833.html
> 
> Всегда надо указывать корректный PIDFile= для сервисов Type=forking:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039831.html
> 
> Максим, можно ли сделать так, чтобы nginx соответствовал
> тем требованиям которые предъявляет systemd к SysV Daemons?
> 
> https://www.freedesktop.org/software/systemd/man/daemon.html

Можно, я ж разве против?

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Igor Sysoev
> On 23 Nov 2017, at 19:28, Gena Makhomed  wrote:
> 
> Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html

Интересно, откуда он это придумал про двойной fork()?

Во FreeBSD используется только один fork() что в 2017 году:
https://svnweb.freebsd.org/base/head/lib/libc/gen/daemon.c?revision=326025=co
что в 1994:
https://svnweb.freebsd.org/base/head/lib/libc/gen/daemon.c?revision=1573=co


-- 
Igor Sysoev
http://nginx.com

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 23.11.2017 17:37, Maxim Dounin wrote:


В systemd's daemon(7) manpage очень подробно расписано
как должны вести себя SysV Daemons при работе с systemd.
И очевидно, что nginx этим требованиям не соответствует.



Original process должен вызывать exit() только после того,
как будет полностью завершена инициализация daemon process,
в частности, после того как daemon process создаст свой pid файл.



Это, что называется, всё очень интересно, но вызывает сомнение
успех подобных рекомендаций.  Особенно с учётом отсутствия
каких-либо внятных примеров того, что же использовать вместо
daemon(3).  О чём я, собственно, и писал выше.


Что использовать вместо daemon(3) документировано в daemon(7):
https://www.freedesktop.org/software/systemd/man/daemon.html

Lennart Poettering очень подробно ответил на этот вопрос в рассылке:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039830.html

Впрочем, если очень хочется использовать все-таки daemon(3) то можно:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039834.html

Кстати, Lennart Poettering нашел еще одну ошибку в исходниках nginx:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039832.html


Впрочем, если верить ответу тут:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039825.html



то соответствующее сообщение можно смело игнорировать, и systemd
на самом деле умеет дожидаться создания pid-файла.  То есть вопрос
лишь в том, что при этом systemd пишет в лог.


Не надо верить тому, что говорит Michael Chapman - он ошибается.
systemd не ждет появления pid-файла, я это проверял по исходникам.

Лучше верить тому, что говорит Lennart Poettering, автор systemd:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039833.html

Всегда надо указывать корректный PIDFile= для сервисов Type=forking:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039831.html

Максим, можно ли сделать так, чтобы nginx соответствовал
тем требованиям которые предъявляет systemd к SysV Daemons?

https://www.freedesktop.org/software/systemd/man/daemon.html

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Maxim Dounin
Hello!

On Thu, Nov 23, 2017 at 03:49:43PM +0200, Gena Makhomed wrote:

> On 22.11.2017 19:43, Maxim Dounin wrote:
> 
> >> systemd: PID file /var/run/nginx.pid not readable (yet?) after start.
> 
> >> Можно ли как-то исправить поведение nginx,
> >> чтобы systemd не флудил в логи сообщениями об ошибках?
> 
> > С точки зрения абстрактного счастья для всех даром - наверное,
> > поведение systemd логично, и на момент выхода запущенного процесса
> > pid-файл должен уже существовать.
> > 
> > С точки зрения практики - паттерн "daemon(); write_pidfile();"
> > используется чуть менее, чем везде, вплоть до соответствующих
> > библиотечных функций.  Так что инициатива выглядит, скажем так,
> > сомнительной.
> 
> Спросил об этом в списке рассылки systemd-devel:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039812.html
> 
> Идея переписать systemd там энтузиазма не вызвала:
> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039820.html
> 
> Более того, мне прислали ссылку на официальную документацию systemd:
> 
> Many other deficiencies with the BSD daemon() function
> are documented in systemd's daemon(7) manpage.
> 
> В systemd's daemon(7) manpage очень подробно расписано
> как должны вести себя SysV Daemons при работе с systemd.
> И очевидно, что nginx этим требованиям не соответствует.
> 
> Original process должен вызывать exit() только после того,
> как будет полностью завершена инициализация daemon process,
> в частности, после того как daemon process создаст свой pid файл.

Это, что называется, всё очень интересно, но вызывает сомнение 
успех подобных рекомендаций.  Особенно с учётом отсутствия 
каких-либо внятных примеров того, что же использовать вместо 
daemon(3).  О чём я, собственно, и писал выше.

Впрочем, если верить ответу тут:

https://lists.freedesktop.org/archives/systemd-devel/2017-November/039825.html

то соответствующее сообщение можно смело игнорировать, и systemd 
на самом деле умеет дожидаться создания pid-файла.  То есть вопрос 
лишь в том, что при этом systemd пишет в лог.

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Re: systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

2017-11-23 Пенетрантность Gena Makhomed

On 22.11.2017 19:43, Maxim Dounin wrote:


systemd: PID file /var/run/nginx.pid not readable (yet?) after start.



Можно ли как-то исправить поведение nginx,
чтобы systemd не флудил в логи сообщениями об ошибках?



С точки зрения абстрактного счастья для всех даром - наверное,
поведение systemd логично, и на момент выхода запущенного процесса
pid-файл должен уже существовать.

С точки зрения практики - паттерн "daemon(); write_pidfile();"
используется чуть менее, чем везде, вплоть до соответствующих
библиотечных функций.  Так что инициатива выглядит, скажем так,
сомнительной.


Спросил об этом в списке рассылки systemd-devel:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039812.html

Идея переписать systemd там энтузиазма не вызвала:
https://lists.freedesktop.org/archives/systemd-devel/2017-November/039820.html

Более того, мне прислали ссылку на официальную документацию systemd:

Many other deficiencies with the BSD daemon() function
are documented in systemd's daemon(7) manpage.

В systemd's daemon(7) manpage очень подробно расписано
как должны вести себя SysV Daemons при работе с systemd.
И очевидно, что nginx этим требованиям не соответствует.

Original process должен вызывать exit() только после того,
как будет полностью завершена инициализация daemon process,
в частности, после того как daemon process создаст свой pid файл.


Проще всего, IMHO, это было бы заткнуть на уровне systemd,
дожидаясь появления pid-файла при необходимости.


Кстати, дожидаться pid-файла - это не совсем тривиальная задача,
ведь nginx пишет свой pid-файл не атомарно. Может же быть так,
что файл уже появился, но он будет нулевого размера и попытка
прочитать из него pid завершится ошибкой? Или он будет частично
записан и тогда из pid-файла прочитается pid другого процесса?

Можно ли будет исправить поведение nginx чтобы он соответствовал
требованиям к SysV Daemons из systemd's daemon(7) manpage?

Поведение systemd изменить не получится, я уже пробовал.

--
Best regards,
 Gena

___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru

Проблемы при написании модуля-замены TLS для NGINX (NoiseSocket)

2017-11-23 Пенетрантность Alexey Ermishkin
Приветствую, меня зовут Алексей. Я работаю в компании VirgilSecurity и
являюсь разработчиком протокола NoiseSocket (noisesocket.com).
Так же наша компания занимается разработкой модуля для NGINX, реализующего
протокол NoiseSocket.
Я хотел бы описать цели, результаты и узнать мнение о решениях и спросить
совета о других путях решения задачи.
Протокол NoiseSocket позиционируется как более простая в реализации и
быстрая альтернатива TLS. Одной  из его главных фич является возможность
установки безопасного соединения без использования сертификатов, используя
лишь "сырые" приватные\публичные ключи. Это необходимо для IoT, бекендов,
p2p и многих других задач.
Основной целью создания модуля для NGINX - это обеспечение функциональности
reverse proxy и load balancing, где соединение между прокси-сервером и
backend серверами осуществляется по протоколу NoiseSocket. Второй целью
является возможность принимать входящие соединения по протоколу NoiseSocket,
то есть обеспечивать поддержку протокола на стороне backend с помощью NGINX.
Для обеспечения нужного функционала модуль должен обеспечить:
1 При создании соединения на стороне noise client инициировать и отработать
handshake phase по алгоритму noise initiator.
2 При входящем соединении на стороне noise server ответить на входящие
handshake сообщения и отработать handshake phase по алгоритму noise .
3 После успешного завершения handshake phase упаковывать/распаковывать
сетевой траффик в NoiseSocket transport messages.
Сначала была рассмотрена возможность создания модуля для контекста http,
однако здесь траффик для сторонних модулей предоставляется в виде
составляющих http, что не дает возможности для работы протокола, имеющего
более низкий уровень, чем http.
Затем был рассмотрен вариант для контекста stream. Однако предоставляемый
функционал для сторонних модулей здесь оказался весьма ограничен. Здесь для
работы протокола уровня представления есть возможность только на стороне
noise server, когда появляется входящее соединение и можно прицепить модуль
к одной из фаз обработки входящего запроса. На стороне noise client такой
возможности нет, потому что здесь имеется функционал только для custom load
balancing. Мы можем добавить свой обработчик:
 ngx_stream_session_t->peer.get(ngx_peer_connection_t *pc,void *data);
Однако его вызов осуществляется до создания соединения:
В файле  ngx_event_connect.c:
ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc)
{
:.
rc = pc->get(pc, pc->data);
:.
c = ngx_get_connection(s, pc->log);
:
}
Таким образом нет никакой возможности инициировать процедуру handshake и
назначить свои обработчики recv, send, recv_chain, send_chain для обработки
траффика средствами стороннего модуля.
В итоге было принято решение создать модуль, реализующий собственный
контекст по обработке траффика. За основу был взят код контекста stream, где
был убран TLS, и добавлен NoiseSocket. 
Для обработки траффика только по протоколу NoiseSocket приемлема следующая
конфигурация, которая наиболее оптимальна по быстродействию:

 https://i.imgur.com/fucb9J0.png

В итоге для сохранения существующего функционала NGINX по обработке http
контента определена следующая конфигурация:

https://i.imgur.com/6vnOdwd.png

или
https://i.imgur.com/WpMhdKh.png

Так как подобная конфигурация не оптимальна в плане быстродействия, то
хотелось бы узнать о более перспективных вариантах внедрения протокола
уровня представления для NGINX в качестве модуля.
Рабочий вариант спецификации для NoiseSocket:
http://noisesocket.com/spec/noisesocket/
 Репозиторий с кодом модуля
https://github.com/VirgilSecurity/virgil-NGINX-noise-socket
___
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru