3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
13 static ngx_int_t
ngx_enable_accept_events(ngx_cycle_t
*cycle
);
14 static ngx_int_t
ngx_disable_accept_events(ngx_cycle_t
*cycle
);
15 static void ngx_close_accepted_connection(ngx_connection_t
*c
);
19 ngx_event_accept(ngx_event_t
*ev
)
26 ngx_event_t
*rev
, *wev
;
28 ngx_connection_t
*c
, *lc
;
29 ngx_event_conf_t
*ecf
;
30 u_char sa
[NGX_SOCKADDRLEN
];
31 #if (NGX_HAVE_ACCEPT4)
32 static ngx_uint_t use_accept4
= 1;
36 if (ngx_enable_accept_events((ngx_cycle_t
*) ngx_cycle
) != NGX_OK
) {
43 ecf
= ngx_event_get_conf(ngx_cycle
->conf_ctx
, ngx_event_core_module
);
45 if (ngx_event_flags
& NGX_USE_RTSIG_EVENT
) {
48 } else if (!(ngx_event_flags
& NGX_USE_KQUEUE_EVENT
)) {
49 ev
->available
= ecf
->multi_accept
;
56 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
57 "accept on %V, ready: %d", &ls
->addr_text
, ev
->available
);
60 socklen
= NGX_SOCKADDRLEN
;
62 #if (NGX_HAVE_ACCEPT4)
64 s
= accept4(lc
->fd
, (struct sockaddr
*) sa
, &socklen
,
67 s
= accept(lc
->fd
, (struct sockaddr
*) sa
, &socklen
);
70 s
= accept(lc
->fd
, (struct sockaddr
*) sa
, &socklen
);
74 err
= ngx_socket_errno
;
76 if (err
== NGX_EAGAIN
) {
77 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, err
,
78 "accept() not ready");
82 level
= NGX_LOG_ALERT
;
84 if (err
== NGX_ECONNABORTED
) {
87 } else if (err
== NGX_EMFILE
|| err
== NGX_ENFILE
) {
91 #if (NGX_HAVE_ACCEPT4)
92 ngx_log_error(level
, ev
->log
, err
,
93 use_accept4
? "accept4() failed" : "accept() failed");
95 if (use_accept4
&& err
== NGX_ENOSYS
) {
97 ngx_inherited_nonblocking
= 0;
101 ngx_log_error(level
, ev
->log
, err
, "accept() failed");
104 if (err
== NGX_ECONNABORTED
) {
105 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
114 if (err
== NGX_EMFILE
|| err
== NGX_ENFILE
) {
115 if (ngx_disable_accept_events((ngx_cycle_t
*) ngx_cycle
)
121 if (ngx_use_accept_mutex
) {
122 if (ngx_accept_mutex_held
) {
123 ngx_shmtx_unlock(&ngx_accept_mutex
);
124 ngx_accept_mutex_held
= 0;
127 ngx_accept_disabled
= 1;
130 ngx_add_timer(ev
, ecf
->accept_mutex_delay
);
138 (void) ngx_atomic_fetch_add(ngx_stat_accepted
, 1);
141 ngx_accept_disabled
= ngx_cycle
->connection_n
/ 8
142 - ngx_cycle
->free_connection_n
;
144 c
= ngx_get_connection(s
, ev
->log
);
147 if (ngx_close_socket(s
) == -1) {
148 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, ngx_socket_errno
,
149 ngx_close_socket_n
" failed");
156 (void) ngx_atomic_fetch_add(ngx_stat_active
, 1);
159 c
->pool
= ngx_create_pool(ls
->pool_size
, ev
->log
);
160 if (c
->pool
== NULL
) {
161 ngx_close_accepted_connection(c
);
165 c
->sockaddr
= ngx_palloc(c
->pool
, socklen
);
166 if (c
->sockaddr
== NULL
) {
167 ngx_close_accepted_connection(c
);
171 ngx_memcpy(c
->sockaddr
, sa
, socklen
);
173 log
= ngx_palloc(c
->pool
, sizeof(ngx_log_t
));
175 ngx_close_accepted_connection(c
);
179 /* set a blocking mode for aio and non-blocking mode for others */
181 if (ngx_inherited_nonblocking
) {
182 if (ngx_event_flags
& NGX_USE_AIO_EVENT
) {
183 if (ngx_blocking(s
) == -1) {
184 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, ngx_socket_errno
,
185 ngx_blocking_n
" failed");
186 ngx_close_accepted_connection(c
);
192 if (!(ngx_event_flags
& (NGX_USE_AIO_EVENT
|NGX_USE_RTSIG_EVENT
))) {
193 if (ngx_nonblocking(s
) == -1) {
194 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, ngx_socket_errno
,
195 ngx_nonblocking_n
" failed");
196 ngx_close_accepted_connection(c
);
206 c
->recv_chain
= ngx_recv_chain
;
207 c
->send_chain
= ngx_send_chain
;
212 c
->socklen
= socklen
;
214 c
->local_sockaddr
= ls
->sockaddr
;
216 c
->unexpected_eof
= 1;
218 #if (NGX_HAVE_UNIX_DOMAIN)
219 if (c
->sockaddr
->sa_family
== AF_UNIX
) {
220 c
->tcp_nopush
= NGX_TCP_NOPUSH_DISABLED
;
221 c
->tcp_nodelay
= NGX_TCP_NODELAY_DISABLED
;
223 /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
234 if (ngx_event_flags
& (NGX_USE_AIO_EVENT
|NGX_USE_RTSIG_EVENT
)) {
235 /* rtsig, aio, iocp */
239 if (ev
->deferred_accept
) {
241 #if (NGX_HAVE_KQUEUE)
250 * TODO: MT: - ngx_atomic_fetch_add()
251 * or protection by critical section or light mutex
253 * TODO: MP: - allocated in a shared memory
254 * - ngx_atomic_fetch_add()
255 * or protection by critical section or light mutex
258 c
->number
= ngx_atomic_fetch_add(ngx_connection_counter
, 1);
261 (void) ngx_atomic_fetch_add(ngx_stat_handled
, 1);
265 rev
->lock
= &c
->lock
;
266 wev
->lock
= &c
->lock
;
267 rev
->own_lock
= &c
->lock
;
268 wev
->own_lock
= &c
->lock
;
272 c
->addr_text
.data
= ngx_pnalloc(c
->pool
, ls
->addr_text_max_len
);
273 if (c
->addr_text
.data
== NULL
) {
274 ngx_close_accepted_connection(c
);
278 c
->addr_text
.len
= ngx_sock_ntop(c
->sockaddr
, c
->addr_text
.data
,
279 ls
->addr_text_max_len
, 0);
280 if (c
->addr_text
.len
== 0) {
281 ngx_close_accepted_connection(c
);
289 struct sockaddr_in
*sin
;
293 struct sockaddr_in6
*sin6
;
297 cidr
= ecf
->debug_connection
.elts
;
298 for (i
= 0; i
< ecf
->debug_connection
.nelts
; i
++) {
299 if (cidr
[i
].family
!= c
->sockaddr
->sa_family
) {
303 switch (cidr
[i
].family
) {
307 sin6
= (struct sockaddr_in6
*) c
->sockaddr
;
308 for (n
= 0; n
< 16; n
++) {
309 if ((sin6
->sin6_addr
.s6_addr
[n
]
310 & cidr
[i
].u
.in6
.mask
.s6_addr
[n
])
311 != cidr
[i
].u
.in6
.addr
.s6_addr
[n
])
319 #if (NGX_HAVE_UNIX_DOMAIN)
324 default: /* AF_INET */
325 sin
= (struct sockaddr_in
*) c
->sockaddr
;
326 if ((sin
->sin_addr
.s_addr
& cidr
[i
].u
.in
.mask
)
327 != cidr
[i
].u
.in
.addr
)
334 log
->log_level
= NGX_LOG_DEBUG_CONNECTION
|NGX_LOG_DEBUG_ALL
;
344 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, log
, 0,
345 "*%d accept: %V fd:%d", c
->number
, &c
->addr_text
, s
);
347 if (ngx_add_conn
&& (ngx_event_flags
& NGX_USE_EPOLL_EVENT
) == 0) {
348 if (ngx_add_conn(c
) == NGX_ERROR
) {
349 ngx_close_accepted_connection(c
);
359 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
363 } while (ev
->available
);
368 ngx_trylock_accept_mutex(ngx_cycle_t
*cycle
)
370 if (ngx_shmtx_trylock(&ngx_accept_mutex
)) {
372 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
373 "accept mutex locked");
375 if (ngx_accept_mutex_held
376 && ngx_accept_events
== 0
377 && !(ngx_event_flags
& NGX_USE_RTSIG_EVENT
))
382 if (ngx_enable_accept_events(cycle
) == NGX_ERROR
) {
383 ngx_shmtx_unlock(&ngx_accept_mutex
);
387 ngx_accept_events
= 0;
388 ngx_accept_mutex_held
= 1;
393 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
394 "accept mutex lock failed: %ui", ngx_accept_mutex_held
);
396 if (ngx_accept_mutex_held
) {
397 if (ngx_disable_accept_events(cycle
) == NGX_ERROR
) {
401 ngx_accept_mutex_held
= 0;
409 ngx_enable_accept_events(ngx_cycle_t
*cycle
)
415 ls
= cycle
->listening
.elts
;
416 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
418 c
= ls
[i
].connection
;
420 if (c
->read
->active
) {
424 if (ngx_event_flags
& NGX_USE_RTSIG_EVENT
) {
426 if (ngx_add_conn(c
) == NGX_ERROR
) {
431 if (ngx_add_event(c
->read
, NGX_READ_EVENT
, 0) == NGX_ERROR
) {
442 ngx_disable_accept_events(ngx_cycle_t
*cycle
)
448 ls
= cycle
->listening
.elts
;
449 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
451 c
= ls
[i
].connection
;
453 if (!c
->read
->active
) {
457 if (ngx_event_flags
& NGX_USE_RTSIG_EVENT
) {
458 if (ngx_del_conn(c
, NGX_DISABLE_EVENT
) == NGX_ERROR
) {
463 if (ngx_del_event(c
->read
, NGX_READ_EVENT
, NGX_DISABLE_EVENT
)
476 ngx_close_accepted_connection(ngx_connection_t
*c
)
480 ngx_free_connection(c
);
483 c
->fd
= (ngx_socket_t
) -1;
485 if (ngx_close_socket(fd
) == -1) {
486 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_socket_errno
,
487 ngx_close_socket_n
" failed");
491 ngx_destroy_pool(c
->pool
);
495 (void) ngx_atomic_fetch_add(ngx_stat_active
, -1);
501 ngx_accept_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
503 return ngx_snprintf(buf
, len
, " while accepting new connection on %V",