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