Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_accept.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 
12 
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);
16 
17 
18 void
20 {
21  socklen_t socklen;
22  ngx_err_t err;
23  ngx_log_t *log;
24  ngx_uint_t level;
25  ngx_socket_t s;
26  ngx_event_t *rev, *wev;
27  ngx_listening_t *ls;
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;
33 #endif
34 
35  if (ev->timedout) {
36  if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
37  return;
38  }
39 
40  ev->timedout = 0;
41  }
42 
44 
46  ev->available = 1;
47 
48  } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
49  ev->available = ecf->multi_accept;
50  }
51 
52  lc = ev->data;
53  ls = lc->listening;
54  ev->ready = 0;
55 
57  "accept on %V, ready: %d", &ls->addr_text, ev->available);
58 
59  do {
60  socklen = NGX_SOCKADDRLEN;
61 
62 #if (NGX_HAVE_ACCEPT4)
63  if (use_accept4) {
64  s = accept4(lc->fd, (struct sockaddr *) sa, &socklen,
65  SOCK_NONBLOCK);
66  } else {
67  s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
68  }
69 #else
70  s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
71 #endif
72 
73  if (s == -1) {
74  err = ngx_socket_errno;
75 
76  if (err == NGX_EAGAIN) {
78  "accept() not ready");
79  return;
80  }
81 
82  level = NGX_LOG_ALERT;
83 
84  if (err == NGX_ECONNABORTED) {
85  level = NGX_LOG_ERR;
86 
87  } else if (err == NGX_EMFILE || err == NGX_ENFILE) {
88  level = NGX_LOG_CRIT;
89  }
90 
91 #if (NGX_HAVE_ACCEPT4)
92  ngx_log_error(level, ev->log, err,
93  use_accept4 ? "accept4() failed" : "accept() failed");
94 
95  if (use_accept4 && err == NGX_ENOSYS) {
96  use_accept4 = 0;
98  continue;
99  }
100 #else
101  ngx_log_error(level, ev->log, err, "accept() failed");
102 #endif
103 
104  if (err == NGX_ECONNABORTED) {
105  if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
106  ev->available--;
107  }
108 
109  if (ev->available) {
110  continue;
111  }
112  }
113 
114  if (err == NGX_EMFILE || err == NGX_ENFILE) {
115  if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
116  != NGX_OK)
117  {
118  return;
119  }
120 
121  if (ngx_use_accept_mutex) {
122  if (ngx_accept_mutex_held) {
125  }
126 
128 
129  } else {
131  }
132  }
133 
134  return;
135  }
136 
137 #if (NGX_STAT_STUB)
138  (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1);
139 #endif
140 
143 
144  c = ngx_get_connection(s, ev->log);
145 
146  if (c == NULL) {
147  if (ngx_close_socket(s) == -1) {
149  ngx_close_socket_n " failed");
150  }
151 
152  return;
153  }
154 
155 #if (NGX_STAT_STUB)
156  (void) ngx_atomic_fetch_add(ngx_stat_active, 1);
157 #endif
158 
159  c->pool = ngx_create_pool(ls->pool_size, ev->log);
160  if (c->pool == NULL) {
161  ngx_close_accepted_connection(c);
162  return;
163  }
164 
165  c->sockaddr = ngx_palloc(c->pool, socklen);
166  if (c->sockaddr == NULL) {
167  ngx_close_accepted_connection(c);
168  return;
169  }
170 
171  ngx_memcpy(c->sockaddr, sa, socklen);
172 
173  log = ngx_palloc(c->pool, sizeof(ngx_log_t));
174  if (log == NULL) {
175  ngx_close_accepted_connection(c);
176  return;
177  }
178 
179  /* set a blocking mode for aio and non-blocking mode for others */
180 
183  if (ngx_blocking(s) == -1) {
185  ngx_blocking_n " failed");
186  ngx_close_accepted_connection(c);
187  return;
188  }
189  }
190 
191  } else {
192  if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
193  if (ngx_nonblocking(s) == -1) {
195  ngx_nonblocking_n " failed");
196  ngx_close_accepted_connection(c);
197  return;
198  }
199  }
200  }
201 
202  *log = ls->log;
203 
204  c->recv = ngx_recv;
205  c->send = ngx_send;
208 
209  c->log = log;
210  c->pool->log = log;
211 
212  c->socklen = socklen;
213  c->listening = ls;
214  c->local_sockaddr = ls->sockaddr;
215 
216  c->unexpected_eof = 1;
217 
218 #if (NGX_HAVE_UNIX_DOMAIN)
219  if (c->sockaddr->sa_family == AF_UNIX) {
222 #if (NGX_SOLARIS)
223  /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
224  c->sendfile = 0;
225 #endif
226  }
227 #endif
228 
229  rev = c->read;
230  wev = c->write;
231 
232  wev->ready = 1;
233 
234  if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
235  /* rtsig, aio, iocp */
236  rev->ready = 1;
237  }
238 
239  if (ev->deferred_accept) {
240  rev->ready = 1;
241 #if (NGX_HAVE_KQUEUE)
242  rev->available = 1;
243 #endif
244  }
245 
246  rev->log = log;
247  wev->log = log;
248 
249  /*
250  * TODO: MT: - ngx_atomic_fetch_add()
251  * or protection by critical section or light mutex
252  *
253  * TODO: MP: - allocated in a shared memory
254  * - ngx_atomic_fetch_add()
255  * or protection by critical section or light mutex
256  */
257 
258  c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
259 
260 #if (NGX_STAT_STUB)
261  (void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
262 #endif
263 
264 #if (NGX_THREADS)
265  rev->lock = &c->lock;
266  wev->lock = &c->lock;
267  rev->own_lock = &c->lock;
268  wev->own_lock = &c->lock;
269 #endif
270 
271  if (ls->addr_ntop) {
273  if (c->addr_text.data == NULL) {
274  ngx_close_accepted_connection(c);
275  return;
276  }
277 
279  ls->addr_text_max_len, 0);
280  if (c->addr_text.len == 0) {
281  ngx_close_accepted_connection(c);
282  return;
283  }
284  }
285 
286 #if (NGX_DEBUG)
287  {
288 
289  struct sockaddr_in *sin;
290  ngx_cidr_t *cidr;
291  ngx_uint_t i;
292 #if (NGX_HAVE_INET6)
293  struct sockaddr_in6 *sin6;
294  ngx_uint_t n;
295 #endif
296 
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) {
300  goto next;
301  }
302 
303  switch (cidr[i].family) {
304 
305 #if (NGX_HAVE_INET6)
306  case AF_INET6:
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])
312  {
313  goto next;
314  }
315  }
316  break;
317 #endif
318 
319 #if (NGX_HAVE_UNIX_DOMAIN)
320  case AF_UNIX:
321  break;
322 #endif
323 
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)
328  {
329  goto next;
330  }
331  break;
332  }
333 
335  break;
336 
337  next:
338  continue;
339  }
340 
341  }
342 #endif
343 
345  "*%d accept: %V fd:%d", c->number, &c->addr_text, s);
346 
348  if (ngx_add_conn(c) == NGX_ERROR) {
349  ngx_close_accepted_connection(c);
350  return;
351  }
352  }
353 
354  log->data = NULL;
355  log->handler = NULL;
356 
357  ls->handler(c);
358 
359  if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
360  ev->available--;
361  }
362 
363  } while (ev->available);
364 }
365 
366 
367 ngx_int_t
369 {
371 
373  "accept mutex locked");
374 
376  && ngx_accept_events == 0
378  {
379  return NGX_OK;
380  }
381 
382  if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
384  return NGX_ERROR;
385  }
386 
387  ngx_accept_events = 0;
389 
390  return NGX_OK;
391  }
392 
394  "accept mutex lock failed: %ui", ngx_accept_mutex_held);
395 
396  if (ngx_accept_mutex_held) {
397  if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
398  return NGX_ERROR;
399  }
400 
402  }
403 
404  return NGX_OK;
405 }
406 
407 
408 static ngx_int_t
409 ngx_enable_accept_events(ngx_cycle_t *cycle)
410 {
411  ngx_uint_t i;
412  ngx_listening_t *ls;
413  ngx_connection_t *c;
414 
415  ls = cycle->listening.elts;
416  for (i = 0; i < cycle->listening.nelts; i++) {
417 
418  c = ls[i].connection;
419 
420  if (c->read->active) {
421  continue;
422  }
423 
425 
426  if (ngx_add_conn(c) == NGX_ERROR) {
427  return NGX_ERROR;
428  }
429 
430  } else {
431  if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
432  return NGX_ERROR;
433  }
434  }
435  }
436 
437  return NGX_OK;
438 }
439 
440 
441 static ngx_int_t
442 ngx_disable_accept_events(ngx_cycle_t *cycle)
443 {
444  ngx_uint_t i;
445  ngx_listening_t *ls;
446  ngx_connection_t *c;
447 
448  ls = cycle->listening.elts;
449  for (i = 0; i < cycle->listening.nelts; i++) {
450 
451  c = ls[i].connection;
452 
453  if (!c->read->active) {
454  continue;
455  }
456 
457  if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
459  return NGX_ERROR;
460  }
461 
462  } else {
464  == NGX_ERROR)
465  {
466  return NGX_ERROR;
467  }
468  }
469  }
470 
471  return NGX_OK;
472 }
473 
474 
475 static void
476 ngx_close_accepted_connection(ngx_connection_t *c)
477 {
478  ngx_socket_t fd;
479 
481 
482  fd = c->fd;
483  c->fd = (ngx_socket_t) -1;
484 
485  if (ngx_close_socket(fd) == -1) {
487  ngx_close_socket_n " failed");
488  }
489 
490  if (c->pool) {
492  }
493 
494 #if (NGX_STAT_STUB)
495  (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
496 #endif
497 }
498 
499 
500 u_char *
501 ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
502 {
503  return ngx_snprintf(buf, len, " while accepting new connection on %V",
504  log->data);
505 }