0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9 #include <ngx_event.h>
|
|
10
|
|
11
|
|
12
|
112
|
13 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
|
0
|
14 static void ngx_select_done(ngx_cycle_t *cycle);
|
324
|
15 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
|
|
16 ngx_uint_t flags);
|
|
17 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
|
|
18 ngx_uint_t flags);
|
112
|
19 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|
20 ngx_uint_t flags);
|
0
|
21 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
|
|
22
|
|
23
|
|
24 static fd_set master_read_fd_set;
|
|
25 static fd_set master_write_fd_set;
|
|
26 static fd_set work_read_fd_set;
|
|
27 static fd_set work_write_fd_set;
|
|
28
|
10
|
29 #if (NGX_WIN32)
|
324
|
30 static ngx_uint_t max_read;
|
|
31 static ngx_uint_t max_write;
|
0
|
32 #else
|
324
|
33 static ngx_int_t max_fd;
|
0
|
34 #endif
|
|
35
|
|
36 static ngx_uint_t nevents;
|
|
37
|
|
38 static ngx_event_t **event_index;
|
|
39
|
|
40
|
|
41 static ngx_str_t select_name = ngx_string("select");
|
|
42
|
|
43 ngx_event_module_t ngx_select_module_ctx = {
|
|
44 &select_name,
|
|
45 NULL, /* create configuration */
|
|
46 ngx_select_init_conf, /* init configuration */
|
|
47
|
|
48 {
|
|
49 ngx_select_add_event, /* add an event */
|
|
50 ngx_select_del_event, /* delete an event */
|
|
51 ngx_select_add_event, /* enable an event */
|
|
52 ngx_select_del_event, /* disable an event */
|
|
53 NULL, /* add an connection */
|
|
54 NULL, /* delete an connection */
|
|
55 NULL, /* process the changes */
|
|
56 ngx_select_process_events, /* process the events */
|
|
57 ngx_select_init, /* init the events */
|
|
58 ngx_select_done /* done the events */
|
|
59 }
|
|
60
|
|
61 };
|
|
62
|
|
63 ngx_module_t ngx_select_module = {
|
58
|
64 NGX_MODULE_V1,
|
0
|
65 &ngx_select_module_ctx, /* module context */
|
|
66 NULL, /* module directives */
|
|
67 NGX_EVENT_MODULE, /* module type */
|
90
|
68 NULL, /* init master */
|
0
|
69 NULL, /* init module */
|
90
|
70 NULL, /* init process */
|
|
71 NULL, /* init thread */
|
|
72 NULL, /* exit thread */
|
|
73 NULL, /* exit process */
|
|
74 NULL, /* exit master */
|
|
75 NGX_MODULE_V1_PADDING
|
0
|
76 };
|
|
77
|
|
78
|
50
|
79 static ngx_int_t
|
112
|
80 ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
|
0
|
81 {
|
|
82 ngx_event_t **index;
|
|
83
|
|
84 if (event_index == NULL) {
|
|
85 FD_ZERO(&master_read_fd_set);
|
|
86 FD_ZERO(&master_write_fd_set);
|
|
87 nevents = 0;
|
|
88 }
|
|
89
|
|
90 if (ngx_process == NGX_PROCESS_WORKER
|
|
91 || cycle->old_cycle == NULL
|
|
92 || cycle->old_cycle->connection_n < cycle->connection_n)
|
|
93 {
|
50
|
94 index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
|
|
95 cycle->log);
|
|
96 if (index == NULL) {
|
|
97 return NGX_ERROR;
|
|
98 }
|
0
|
99
|
|
100 if (event_index) {
|
|
101 ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
|
|
102 ngx_free(event_index);
|
|
103 }
|
112
|
104
|
0
|
105 event_index = index;
|
|
106 }
|
|
107
|
|
108 ngx_io = ngx_os_io;
|
|
109
|
|
110 ngx_event_actions = ngx_select_module_ctx.actions;
|
|
111
|
112
|
112 ngx_event_flags = NGX_USE_LEVEL_EVENT;
|
0
|
113
|
10
|
114 #if (NGX_WIN32)
|
0
|
115 max_read = max_write = 0;
|
|
116 #else
|
|
117 max_fd = -1;
|
|
118 #endif
|
|
119
|
|
120 return NGX_OK;
|
|
121 }
|
|
122
|
|
123
|
50
|
124 static void
|
|
125 ngx_select_done(ngx_cycle_t *cycle)
|
0
|
126 {
|
|
127 ngx_free(event_index);
|
|
128
|
|
129 event_index = NULL;
|
|
130 }
|
|
131
|
|
132
|
50
|
133 static ngx_int_t
|
324
|
134 ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
|
0
|
135 {
|
|
136 ngx_connection_t *c;
|
|
137
|
|
138 c = ev->data;
|
|
139
|
|
140 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
324
|
141 "select add event fd:%d ev:%i", c->fd, event);
|
0
|
142
|
|
143 if (ev->index != NGX_INVALID_INDEX) {
|
|
144 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
|
324
|
145 "select event fd:%d ev:%i is already set", c->fd, event);
|
0
|
146 return NGX_OK;
|
|
147 }
|
|
148
|
10
|
149 #if (NGX_WIN32)
|
0
|
150
|
|
151 if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE)
|
|
152 || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE))
|
|
153 {
|
|
154 ngx_log_error(NGX_LOG_ERR, ev->log, 0,
|
|
155 "maximum number of descriptors "
|
|
156 "supported by select() is %d", FD_SETSIZE);
|
|
157 return NGX_ERROR;
|
|
158 }
|
|
159
|
|
160 if (event == NGX_READ_EVENT) {
|
|
161 FD_SET(c->fd, &master_read_fd_set);
|
|
162 max_read++;
|
|
163
|
|
164 } else if (event == NGX_WRITE_EVENT) {
|
|
165 FD_SET(c->fd, &master_write_fd_set);
|
|
166 max_write++;
|
|
167 }
|
|
168
|
|
169 #else
|
|
170
|
|
171 if (event == NGX_READ_EVENT) {
|
|
172 FD_SET(c->fd, &master_read_fd_set);
|
|
173
|
|
174 } else if (event == NGX_WRITE_EVENT) {
|
|
175 FD_SET(c->fd, &master_write_fd_set);
|
|
176 }
|
|
177
|
|
178 if (max_fd != -1 && max_fd < c->fd) {
|
|
179 max_fd = c->fd;
|
|
180 }
|
|
181
|
|
182 #endif
|
|
183
|
|
184 ev->active = 1;
|
|
185
|
|
186 event_index[nevents] = ev;
|
|
187 ev->index = nevents;
|
|
188 nevents++;
|
|
189
|
|
190 return NGX_OK;
|
|
191 }
|
|
192
|
|
193
|
50
|
194 static ngx_int_t
|
324
|
195 ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
|
0
|
196 {
|
|
197 ngx_connection_t *c;
|
|
198
|
|
199 c = ev->data;
|
|
200
|
|
201 ev->active = 0;
|
|
202
|
|
203 if (ev->index == NGX_INVALID_INDEX) {
|
|
204 return NGX_OK;
|
|
205 }
|
|
206
|
|
207 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
324
|
208 "select del event fd:%d ev:%i", c->fd, event);
|
0
|
209
|
10
|
210 #if (NGX_WIN32)
|
0
|
211
|
|
212 if (event == NGX_READ_EVENT) {
|
|
213 FD_CLR(c->fd, &master_read_fd_set);
|
|
214 max_read--;
|
|
215
|
|
216 } else if (event == NGX_WRITE_EVENT) {
|
|
217 FD_CLR(c->fd, &master_write_fd_set);
|
|
218 max_write--;
|
|
219 }
|
|
220
|
|
221 #else
|
|
222
|
|
223 if (event == NGX_READ_EVENT) {
|
|
224 FD_CLR(c->fd, &master_read_fd_set);
|
|
225
|
|
226 } else if (event == NGX_WRITE_EVENT) {
|
|
227 FD_CLR(c->fd, &master_write_fd_set);
|
|
228 }
|
|
229
|
|
230 if (max_fd == c->fd) {
|
|
231 max_fd = -1;
|
|
232 }
|
|
233
|
|
234 #endif
|
|
235
|
324
|
236 if (ev->index < --nevents) {
|
0
|
237 event_index[ev->index] = event_index[nevents];
|
|
238 event_index[ev->index]->index = ev->index;
|
|
239 }
|
|
240
|
|
241 ev->index = NGX_INVALID_INDEX;
|
|
242
|
|
243 return NGX_OK;
|
|
244 }
|
|
245
|
|
246
|
50
|
247 static ngx_int_t
|
112
|
248 ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|
249 ngx_uint_t flags)
|
0
|
250 {
|
112
|
251 int ready, nready;
|
|
252 ngx_uint_t i, found;
|
|
253 ngx_err_t err;
|
|
254 ngx_event_t *ev, **queue;
|
|
255 ngx_connection_t *c;
|
|
256 struct timeval tv, *tp;
|
|
257 #if !(NGX_WIN32)
|
|
258 ngx_uint_t level;
|
0
|
259 #endif
|
|
260
|
10
|
261 #if !(NGX_WIN32)
|
0
|
262
|
|
263 if (max_fd == -1) {
|
|
264 for (i = 0; i < nevents; i++) {
|
|
265 c = event_index[i]->data;
|
|
266 if (max_fd < c->fd) {
|
|
267 max_fd = c->fd;
|
|
268 }
|
|
269 }
|
|
270
|
|
271 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
272 "change max_fd: %d", max_fd);
|
|
273 }
|
|
274
|
|
275 #endif
|
|
276
|
|
277 #if (NGX_DEBUG)
|
|
278 if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
|
|
279 for (i = 0; i < nevents; i++) {
|
|
280 ev = event_index[i];
|
|
281 c = ev->data;
|
|
282 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
283 "select event: fd:%d wr:%d", c->fd, ev->write);
|
|
284 }
|
|
285
|
10
|
286 #if !(NGX_WIN32)
|
0
|
287 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
288 "max_fd: %d", max_fd);
|
|
289 #endif
|
|
290 }
|
|
291 #endif
|
|
292
|
|
293 if (timer == NGX_TIMER_INFINITE) {
|
|
294 tp = NULL;
|
|
295
|
|
296 } else {
|
106
|
297 tv.tv_sec = (long) (timer / 1000);
|
|
298 tv.tv_usec = (long) ((timer % 1000) * 1000);
|
0
|
299 tp = &tv;
|
|
300 }
|
|
301
|
|
302 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
106
|
303 "select timer: %M", timer);
|
0
|
304
|
|
305 work_read_fd_set = master_read_fd_set;
|
|
306 work_write_fd_set = master_write_fd_set;
|
|
307
|
36
|
308 #if 1
|
0
|
309 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
36
|
310 /*
|
|
311 * (void *) disables "dereferencing type-punned
|
|
312 * pointer will break strict-aliasing rules
|
|
313 */
|
|
314 "select read fd_set: %08Xd",
|
|
315 *(int *) (void *) &work_read_fd_set);
|
|
316 #endif
|
0
|
317
|
10
|
318 #if (NGX_WIN32)
|
112
|
319
|
0
|
320 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
|
112
|
321
|
0
|
322 #else
|
112
|
323
|
0
|
324 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
|
112
|
325
|
0
|
326 #endif
|
|
327
|
|
328 if (ready == -1) {
|
|
329 err = ngx_socket_errno;
|
|
330 } else {
|
|
331 err = 0;
|
|
332 }
|
|
333
|
112
|
334 if (flags & NGX_UPDATE_TIME) {
|
|
335 ngx_time_update(0, 0);
|
|
336 }
|
0
|
337
|
|
338 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
339 "select ready %d", ready);
|
|
340
|
112
|
341 #if (NGX_WIN32)
|
|
342
|
0
|
343 if (err) {
|
|
344 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
|
|
345 return NGX_ERROR;
|
|
346 }
|
|
347
|
112
|
348 #else
|
0
|
349
|
112
|
350 if (err) {
|
|
351 if (err == NGX_EINTR) {
|
|
352
|
|
353 if (ngx_event_timer_alarm) {
|
|
354 ngx_event_timer_alarm = 0;
|
|
355 return NGX_OK;
|
|
356 }
|
126
|
357
|
112
|
358 level = NGX_LOG_INFO;
|
126
|
359
|
|
360 } else {
|
112
|
361 level = NGX_LOG_ALERT;
|
|
362 }
|
|
363
|
|
364 ngx_log_error(level, cycle->log, err, "select() failed");
|
0
|
365 return NGX_ERROR;
|
|
366 }
|
|
367
|
112
|
368 #endif
|
|
369
|
116
|
370 if (ready == 0) {
|
|
371 if (timer != NGX_TIMER_INFINITE) {
|
|
372 return NGX_OK;
|
|
373 }
|
|
374
|
|
375 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
|
376 "select() returned no events without timeout");
|
|
377 return NGX_ERROR;
|
112
|
378 }
|
|
379
|
|
380 ngx_mutex_lock(ngx_posted_events_mutex);
|
|
381
|
0
|
382 nready = 0;
|
|
383
|
|
384 for (i = 0; i < nevents; i++) {
|
|
385 ev = event_index[i];
|
|
386 c = ev->data;
|
|
387 found = 0;
|
|
388
|
|
389 if (ev->write) {
|
|
390 if (FD_ISSET(c->fd, &work_write_fd_set)) {
|
|
391 found = 1;
|
|
392 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
393 "select write %d", c->fd);
|
|
394 }
|
|
395
|
|
396 } else {
|
|
397 if (FD_ISSET(c->fd, &work_read_fd_set)) {
|
|
398 found = 1;
|
|
399 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
|
400 "select read %d", c->fd);
|
|
401 }
|
|
402 }
|
|
403
|
|
404 if (found) {
|
|
405 ev->ready = 1;
|
|
406
|
112
|
407 queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
|
|
408 &ngx_posted_events);
|
126
|
409 ngx_locked_post_event(ev, queue);
|
0
|
410
|
|
411 nready++;
|
|
412 }
|
|
413 }
|
|
414
|
112
|
415 ngx_mutex_unlock(ngx_posted_events_mutex);
|
0
|
416
|
|
417 if (ready != nready) {
|
|
418 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events");
|
|
419 }
|
|
420
|
|
421 return NGX_OK;
|
|
422 }
|
|
423
|
|
424
|
50
|
425 static char *
|
|
426 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
|
0
|
427 {
|
|
428 ngx_event_conf_t *ecf;
|
|
429
|
|
430 ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
|
|
431
|
|
432 if (ecf->use != ngx_select_module.ctx_index) {
|
|
433 return NGX_CONF_OK;
|
|
434 }
|
|
435
|
|
436 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */
|
|
437
|
10
|
438 #if !(NGX_WIN32)
|
112
|
439
|
0
|
440 if ((unsigned) ecf->connections > FD_SETSIZE) {
|
|
441 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
|
|
442 "the maximum number of files "
|
|
443 "supported by select() is " ngx_value(FD_SETSIZE));
|
|
444 return NGX_CONF_ERROR;
|
|
445 }
|
112
|
446
|
0
|
447 #endif
|
|
448
|
10
|
449 #if (NGX_THREADS) && !(NGX_WIN32)
|
112
|
450
|
0
|
451 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
|
|
452 "select() is not supported in the threaded mode");
|
|
453 return NGX_CONF_ERROR;
|
112
|
454
|
0
|
455 #else
|
112
|
456
|
0
|
457 return NGX_CONF_OK;
|
112
|
458
|
0
|
459 #endif
|
|
460 }
|