blob: 7e877617fdba3726c764c5b0ab9082f94d0831bf [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
2#include <ngx_config.h>
Igor Sysoev0ad17c02002-08-26 15:18:19 +00003#include <ngx_core.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00004#include <ngx_event.h>
Igor Sysoev7578ec92003-06-02 15:24:30 +00005#include <nginx.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00006
7
Igor Sysoevd581fd52003-05-13 16:02:32 +00008void ngx_event_accept(ngx_event_t *ev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00009{
Igor Sysoev6b863e32003-05-12 15:52:24 +000010 int instance;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000011 socklen_t len;
12 struct sockaddr *sa;
Igor Sysoev42feecb2002-12-15 06:25:09 +000013 ngx_err_t err;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000014 ngx_pool_t *pool;
Igor Sysoev42feecb2002-12-15 06:25:09 +000015 ngx_socket_t s;
16 ngx_event_t *rev, *wev;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000017 ngx_connection_t *c, *ls;
Igor Sysoev13933252003-05-29 13:02:09 +000018 ngx_event_conf_t *ecf;
Igor Sysoev42feecb2002-12-15 06:25:09 +000019
Igor Sysoev13933252003-05-29 13:02:09 +000020 ecf = ngx_event_get_conf(ngx_event_module);
21
22 ls = ev->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000023
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000024 ngx_log_debug(ev->log, "ngx_event_accept: accept ready: %d" _
25 ev->available);
Igor Sysoev86de4cb2003-01-30 07:28:09 +000026
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000027 ev->ready = 0;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000028
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000029 do {
Igor Sysoev1c13c662003-05-20 15:37:55 +000030
Igor Sysoev7578ec92003-06-02 15:24:30 +000031 /*
32 * Create the pool before accept() to avoid copy the sockaddr.
Igor Sysoev239baac2003-06-11 15:28:34 +000033 * Although accept() can fail it's an uncommon case
Igor Sysoev7578ec92003-06-02 15:24:30 +000034 * and the pool can be got from the free pool list
35 */
Igor Sysoev1c13c662003-05-20 15:37:55 +000036
Igor Sysoev239baac2003-06-11 15:28:34 +000037 pool = ngx_create_pool(ls->listening->pool_size, ev->log);
Igor Sysoevd581fd52003-05-13 16:02:32 +000038 if (pool == NULL) {
39 return;
40 }
Igor Sysoev86de4cb2003-01-30 07:28:09 +000041
Igor Sysoev239baac2003-06-11 15:28:34 +000042 sa = ngx_palloc(pool, ls->listening->socklen);
Igor Sysoevd581fd52003-05-13 16:02:32 +000043 if (sa == NULL) {
44 return;
45 }
46
Igor Sysoev239baac2003-06-11 15:28:34 +000047 len = ls->listening->socklen;
48
49ngx_log_debug(ev->log, "ADDR %s" _ ls->listening->addr_text.data);
Igor Sysoev86de4cb2003-01-30 07:28:09 +000050
51 s = accept(ls->fd, sa, &len);
52 if (s == -1) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000053 err = ngx_socket_errno;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000054
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000055 if (err == NGX_EAGAIN) {
Igor Sysoev86de4cb2003-01-30 07:28:09 +000056 ngx_log_error(NGX_LOG_NOTICE, ev->log, err,
Igor Sysoev239baac2003-06-11 15:28:34 +000057 "EAGAIN while accept() %s",
58 ls->listening->addr_text.data);
Igor Sysoevd581fd52003-05-13 16:02:32 +000059 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000060 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +000061
Igor Sysoev86de4cb2003-01-30 07:28:09 +000062 ngx_log_error(NGX_LOG_ALERT, ev->log, err,
Igor Sysoev239baac2003-06-11 15:28:34 +000063 "accept() %s failed", ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +000064
65 ngx_destroy_pool(pool);
66 return;
67 }
68
Igor Sysoevaa3436c2003-05-30 14:27:59 +000069 /* disable warnings: Win32 SOCKET is u_int while UNIX socket is int */
70 if ((unsigned) s >= (unsigned) ecf->connections) {
Igor Sysoev13933252003-05-29 13:02:09 +000071
72 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
73 "accept() %s returned socket #%d while "
74 "only %d connections was configured, "
75 "sleeping for 1 second",
Igor Sysoev239baac2003-06-11 15:28:34 +000076 ls->listening->addr_text.data, s, ecf->connections);
Igor Sysoev13933252003-05-29 13:02:09 +000077
78 if (ngx_close_socket(s) == -1) {
79 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
80 ngx_close_socket_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +000081 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +000082 }
83
Igor Sysoev1c104622003-06-03 15:42:58 +000084 ngx_msleep(1000);
Igor Sysoev13933252003-05-29 13:02:09 +000085
86 ngx_destroy_pool(pool);
Igor Sysoevd581fd52003-05-13 16:02:32 +000087 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000088 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +000089
Igor Sysoevfa73aac2003-05-21 13:28:21 +000090 /* set a blocking mode for aio and non-blocking mode for others */
Igor Sysoev73009772003-02-06 17:21:13 +000091
Igor Sysoevfa73aac2003-05-21 13:28:21 +000092 if (ngx_inherited_nonblocking) {
93 if ((ngx_event_flags & NGX_USE_AIO_EVENT)) {
94 if (ngx_blocking(s) == -1) {
95 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
96 ngx_blocking_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +000097 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +000098
99 if (ngx_close_socket(s) == -1) {
100 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
101 ngx_close_socket_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +0000102 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +0000103 }
104
105 ngx_destroy_pool(pool);
Igor Sysoevfa73aac2003-05-21 13:28:21 +0000106 return;
107 }
108 }
Igor Sysoev73009772003-02-06 17:21:13 +0000109
Igor Sysoevfa73aac2003-05-21 13:28:21 +0000110 } else {
111 if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) {
112 if (ngx_nonblocking(s) == -1) {
113 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
114 ngx_nonblocking_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +0000115 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +0000116
117 if (ngx_close_socket(s) == -1) {
118 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
119 ngx_close_socket_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +0000120 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +0000121 }
122
123 ngx_destroy_pool(pool);
Igor Sysoevfa73aac2003-05-21 13:28:21 +0000124 return;
125 }
Igor Sysoev73009772003-02-06 17:21:13 +0000126 }
127 }
Igor Sysoev73009772003-02-06 17:21:13 +0000128
Igor Sysoev239baac2003-06-11 15:28:34 +0000129#if (WIN32)
130 /*
131 * Winsock assignes a socket number divisible by 4
132 * so to find a connection we divide a socket number by 4.
133 */
134
135 if (s % 4) {
136 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
137 ngx_socket_n " created socket %d", s);
138 exit(1);
139 }
140
141 rev = &ngx_read_events[s / 4];
142 wev = &ngx_write_events[s / 4];
143 c = &ngx_connections[s / 4];
144#else
Igor Sysoev42feecb2002-12-15 06:25:09 +0000145 rev = &ngx_read_events[s];
146 wev = &ngx_write_events[s];
147 c = &ngx_connections[s];
Igor Sysoev239baac2003-06-11 15:28:34 +0000148#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000149
Igor Sysoev6b863e32003-05-12 15:52:24 +0000150 instance = rev->instance;
151
Igor Sysoev42feecb2002-12-15 06:25:09 +0000152 ngx_memzero(rev, sizeof(ngx_event_t));
153 ngx_memzero(wev, sizeof(ngx_event_t));
154 ngx_memzero(c, sizeof(ngx_connection_t));
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000155
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000156 c->pool = pool;
157
Igor Sysoev239baac2003-06-11 15:28:34 +0000158 c->listening = ls->listening;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000159 c->sockaddr = sa;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000160 c->socklen = len;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000161
Igor Sysoev6b863e32003-05-12 15:52:24 +0000162 rev->instance = wev->instance = !instance;
163
Igor Sysoev42feecb2002-12-15 06:25:09 +0000164 rev->index = wev->index = NGX_INVALID_INDEX;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000165
Igor Sysoev42feecb2002-12-15 06:25:09 +0000166 rev->data = wev->data = c;
167 c->read = rev;
168 c->write = wev;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000169
Igor Sysoev42feecb2002-12-15 06:25:09 +0000170 c->fd = s;
171 c->unexpected_eof = 1;
172 wev->write = 1;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000173
Igor Sysoev9e4920b2003-04-14 17:04:58 +0000174 if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) {
Igor Sysoev73009772003-02-06 17:21:13 +0000175 wev->ready = 1;
176 }
Igor Sysoev73009772003-02-06 17:21:13 +0000177
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000178 c->ctx = ls->ctx;
179 c->servers = ls->servers;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000180
Igor Sysoevd581fd52003-05-13 16:02:32 +0000181 c->log = ngx_palloc(c->pool, sizeof(ngx_log_t));
182 if (c->log == NULL) {
183 return;
184 }
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000185 ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t));
186 rev->log = wev->log = c->log;
187
Igor Sysoev7578ec92003-06-02 15:24:30 +0000188 /* TODO: x86: MT: lock xadd, MP: lock xadd, shared */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000189 c->number = ngx_connection_counter++;
190
Igor Sysoev13933252003-05-29 13:02:09 +0000191 ngx_log_debug(ev->log, "accept: %d, %d" _ s _ c->number);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000192
Igor Sysoev13933252003-05-29 13:02:09 +0000193 if (ev->deferred_accept) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000194 rev->ready = 1;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000195 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000196
Igor Sysoev13933252003-05-29 13:02:09 +0000197 if (ngx_add_conn) {
198 if (ngx_add_conn(c) == NGX_ERROR) {
199 if (ngx_close_socket(s) == -1) {
200 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
201 ngx_close_socket_n " %s failed",
Igor Sysoev239baac2003-06-11 15:28:34 +0000202 ls->listening->addr_text.data);
Igor Sysoev13933252003-05-29 13:02:09 +0000203 }
Igor Sysoev6a644c62003-03-04 06:33:48 +0000204
Igor Sysoev13933252003-05-29 13:02:09 +0000205 ngx_destroy_pool(pool);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000206 return;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000207 }
208 }
209
Igor Sysoev239baac2003-06-11 15:28:34 +0000210 ls->listening->handler(c);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000211
Igor Sysoeva9830112003-05-19 16:39:14 +0000212 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000213 ev->available--;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000214 }
215
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000216 } while (ev->available);
Igor Sysoev6253ca12003-05-27 12:18:54 +0000217
Igor Sysoevd581fd52003-05-13 16:02:32 +0000218 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000219}