Re: Когда может возникнуть ситуация, что rev->instance != instance?

Валентин Бартенев vbart at nginx.com
Fri Sep 27 17:06:14 UTC 2013


On Friday 27 September 2013 20:45:27 megalodon wrote:
> Пытаюсь вникнуть в мысль: "Мы могли закрыть соединение до того, как
> добрались до обработки событий". Но где в промежутке между epoll_wait() и
> итерацией цикла, в которой мы обрабатываем событие то место, где мы можем
> потенциально закрыть сокет?

"событий, с ним связанных"

[...]
> 
>     for (i = 0; i < events; i++) {
>         c = event_list[i].data.ptr;
> 
>         instance = (uintptr_t) c & 1;
>         c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
> 
>         rev = c->read;
> 
>         if (c->fd == -1 || rev->instance != instance) {
> 
> Если c->fd не равно -1 и если  rev->instance не совпадает с instance, то
> получается, что где-то между строками
>  events = epoll_wait(ep, event_list, (int) nevents, timer);   и
>    .....
>  if (c->fd == -1 || rev->instance != instance) {
> произошло инвертирование этого поля?
> 

Между этими строками ещё происходят итерации цикла, которые итерирует
по другим событиям, возвращенным из epoll_wait().

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

Всё становится ещё сложнее, когда у нас есть, например, какой-нибудь
SSI, который асинхронно пошел сразу на несколько бэкендов.  Представьте,
что в этот момент клиент закрыл соединение и мы по этому событию
автоматически закрываем все соединения с бэкендами, открытыми SSI-модулем
для обслуживания запроса от этого клиента.

> 
> "Несоответствие instance возможно, когда мы уже закрыли соединение, про
> которое нам сообщает ядро." Получается, что пока процесс спал, будучи
> заблокированным на шаге epoll_wait(), каким-то образом сокет закрылся и
> структура ngx_connection_t была использована повторно, но как, ведь процесс
> был заблокирован?
> 

Нет, не так.  Максим в своем ответе уже привел пример.  Смотрите и мой выше.  
Соединение могло быть закрыто, а равно как открыто другое соединение при 
обработки других событий в цикле.

--
Валентин Бартенев
http://nginx.org/en/donation.html


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