[PATCH] Workaround for "configuration file test failed" under OpenVZ.

Gena Makhomed gmm на csdoc.com
Чт Июл 23 18:30:49 UTC 2015


Здравствуйте!

Патч в аттаче.

Иногда nginx -t падает с ошибкой "98: Address already in use"
nginx: configuration file /etc/nginx/nginx.conf test failed

Хотя конфиг нормальный. Такая проблема встречается на VDS/VPS
после того как контейнер был мигрирован на другую hardware node
или после suspend/resume.

По сути - сейчас эта ошибка присутствует везде на OpenVZ + nginx.
А VDS/VPS на базе OpenVZ с nginx в мире используется очень много.

Информацию по эту ошибку OpenVZ в баг-трекер OpenVZ я зарепортил
еще в 2012 году: https://bugzilla.openvz.org/show_bug.cgi?id=2470
но когда ее исправят не понятно. Даже если исправят в новой версии
OpenVZ - очень многие хостинг-провайдеры не спешат обновлять свои
сервера и там вполне могут годами использоваться старые версии ядра.

Этот глюк ядра выглядит так, словно это ошибка в коде nginx
И пользователи будут скорее всего думать, что это nginx кривой.

Пользователи VDS/VPS на базе OpenVZ могут быстрее обновить nginx
из официального репозитория, используя самую новую версию nginx.

Вопрос - может быть имеет смысл добавить
workaround для этого бага OpenVZ в код nginx?

Эту проблему обсуждали в списке рассылки nginx еще в 2011 году:
http://mailman.nginx.org/pipermail/nginx/2011-April/thread.html#26246
http://forum.nginx.org/read.php?2,191227,191227
- но ведь ничего так и не изменилось до сих пор.

Сейчас при тестировании конфигурации nginx пытается сделать
bind() и если не получилось - дальше не идет. Но если вдруг
получилось сделать bind() - он после этого пытается сделать
listen() и потом тестирование конфига завершается с ошибкой:
nginx: configuration file /etc/nginx/nginx.conf test failed

Дополнительная информация по этой проблеме:
http://lists.openvz.org/pipermail/users/2015-July/006358.html

Патч:

===========================================================================

# HG changeset patch
# User Gena Makhomed <gmm at csdoc.com>
# Date 1437674403 14400
#      Thu Jul 23 14:00:03 2015 -0400
# Node ID 57ac65580b5bba0cb4bb61dca9d63daec0ceb14c
# Parent  341e4303d25be159d4773b819d0ec055ba711afb
Workaround for "configuration file test failed" under OpenVZ.

nginx configuration test failed:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address 
already in use)
nginx: configuration file /etc/nginx/nginx.conf test failed

...if nginx used under OpenVZ and container with nginx was suspended and 
resumed.

After this patch - nginx configuration test works fine under same 
environment:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

PS More details about OpenVZ suspend/resume bug:
https://bugzilla.openvz.org/show_bug.cgi?id=2470

diff -r 341e4303d25b -r 57ac65580b5b src/core/ngx_connection.c
--- a/src/core/ngx_connection.c	Thu Jul 16 14:20:48 2015 +0300
+++ b/src/core/ngx_connection.c	Thu Jul 23 14:00:03 2015 -0400
@@ -567,9 +567,13 @@
  #endif

              if (listen(s, ls[i].backlog) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                              "listen() to %V, backlog %d failed",
-                              &ls[i].addr_text, ls[i].backlog);
+                err = ngx_socket_errno;
+
+                if (err != NGX_EADDRINUSE || !ngx_test_config) {
+                    ngx_log_error(NGX_LOG_EMERG, log, err,
+                                  "listen() to %V, backlog %d failed",
+                                  &ls[i].addr_text, ls[i].backlog);
+                }

                  if (ngx_close_socket(s) == -1) {
                      ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
@@ -577,7 +581,15 @@
                                    &ls[i].addr_text);
                  }

-                return NGX_ERROR;
+                if (err != NGX_EADDRINUSE) {
+                    return NGX_ERROR;
+                }
+
+                if (!ngx_test_config) {
+                    failed = 1;
+                }
+
+                continue;
              }

              ls[i].listen = 1;

===========================================================================

-- 
Best regards,
  Gena
-------------- next part --------------
# HG changeset patch
# User Gena Makhomed <gmm at csdoc.com>
# Date 1437674403 14400
#      Thu Jul 23 14:00:03 2015 -0400
# Node ID 57ac65580b5bba0cb4bb61dca9d63daec0ceb14c
# Parent  341e4303d25be159d4773b819d0ec055ba711afb
Workaround for "configuration file test failed" under OpenVZ.

nginx configuration test failed:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address already in use)
nginx: configuration file /etc/nginx/nginx.conf test failed

...if nginx used under OpenVZ and container with nginx was suspended and resumed.

After this patch - nginx configuration test works fine under same environment:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

PS More details about OpenVZ suspend/resume bug:
https://bugzilla.openvz.org/show_bug.cgi?id=2470

diff -r 341e4303d25b -r 57ac65580b5b src/core/ngx_connection.c
--- a/src/core/ngx_connection.c	Thu Jul 16 14:20:48 2015 +0300
+++ b/src/core/ngx_connection.c	Thu Jul 23 14:00:03 2015 -0400
@@ -567,9 +567,13 @@
 #endif
 
             if (listen(s, ls[i].backlog) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                              "listen() to %V, backlog %d failed",
-                              &ls[i].addr_text, ls[i].backlog);
+                err = ngx_socket_errno;
+
+                if (err != NGX_EADDRINUSE || !ngx_test_config) {
+                    ngx_log_error(NGX_LOG_EMERG, log, err,
+                                  "listen() to %V, backlog %d failed",
+                                  &ls[i].addr_text, ls[i].backlog);
+                }
 
                 if (ngx_close_socket(s) == -1) {
                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
@@ -577,7 +581,15 @@
                                   &ls[i].addr_text);
                 }
 
-                return NGX_ERROR;
+                if (err != NGX_EADDRINUSE) {
+                    return NGX_ERROR;
+                }
+
+                if (!ngx_test_config) {
+                    failed = 1;
+                }
+
+                continue;
             }
 
             ls[i].listen = 1;


Подробная информация о списке рассылки nginx-ru