这些天,我正在研究nginx源代码。
但是有一个关于陈旧事件的问题。 如果有即将到来的事件:#1,#2,#3 ..#40, 当我们处理#1时,#40将关闭,它的变量实例为0 和#2.#3是一个新的连接, 接受函数来分配一个只是免费的新描述符(#40), 当我们处理#2时, 我们需要调用名为ngx_event_accept的函数,然后调用ngx_get_connection, 但不幸的是,在那之后,我们失败了,这意味着我们需要释放连接,但是我们已经调用了一次ngx_get_connection,这意味着变量实例已经改变了一次。 就像下面的代码(成功和失败)
void ngx_event_accept(ngx_event_t *ev)
{
...
/* success */
c = ngx_get_connection(s, ev->log);
if (c == NULL) {
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
return;
}
c->type = SOCK_STREAM;
...
/* failed */
c->pool = ngx_create_pool(ls->pool_size, ev->log);
if (c->pool == NULL) {
ngx_close_accepted_connection(c);
return;
}
c->sockaddr = ngx_palloc(c->pool, socklen);
if (c->sockaddr == NULL) {
ngx_close_accepted_connection(c);
return;
}
ngx_memcpy(c->sockaddr, sa, socklen);
/* or failed here */
log = ngx_palloc(c->pool, sizeof(ngx_log_t));
if (log == NULL) {
ngx_close_accepted_connection(c);
return;
}
....
}
当我们处理#3时,我们成功,fd设置为40,并且实例的值再次改变。 现在它与之前相同,因此名为ngx_epoll_process_events的函数中的以下判断语句将不起作用,
if (c->fd == -1 || rev->instance != instance) {
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: stale event %p", c);
continue;
}
我知道它可以发布队列中没有处理的事件,但如果我不使用ngx_use_accept_mutex,这意味着函数ngx_process_events_and_timers中的标志不包含NGX_POST_EVENTS, 在这种情况下,它不会发布事件,但会立即处理事件,这是错误的,因为#40是陈旧事件。