Annotation of embedaddon/nginx/src/event/modules/ngx_win32_select_module.c, revision 1.1.1.1
1.1 misho 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_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
14: static void ngx_select_done(ngx_cycle_t *cycle);
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);
19: static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
20: ngx_uint_t flags);
21: static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
22: static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
23:
24:
25: static fd_set master_read_fd_set;
26: static fd_set master_write_fd_set;
27: static fd_set work_read_fd_set;
28: static fd_set work_write_fd_set;
29:
30: static ngx_uint_t max_read;
31: static ngx_uint_t max_write;
32: static ngx_uint_t nevents;
33:
34: static ngx_event_t **event_index;
35:
36:
37: static ngx_str_t select_name = ngx_string("select");
38:
39: ngx_event_module_t ngx_select_module_ctx = {
40: &select_name,
41: NULL, /* create configuration */
42: ngx_select_init_conf, /* init configuration */
43:
44: {
45: ngx_select_add_event, /* add an event */
46: ngx_select_del_event, /* delete an event */
47: ngx_select_add_event, /* enable an event */
48: ngx_select_del_event, /* disable an event */
49: NULL, /* add an connection */
50: NULL, /* delete an connection */
51: NULL, /* process the changes */
52: ngx_select_process_events, /* process the events */
53: ngx_select_init, /* init the events */
54: ngx_select_done /* done the events */
55: }
56:
57: };
58:
59: ngx_module_t ngx_select_module = {
60: NGX_MODULE_V1,
61: &ngx_select_module_ctx, /* module context */
62: NULL, /* module directives */
63: NGX_EVENT_MODULE, /* module type */
64: NULL, /* init master */
65: NULL, /* init module */
66: NULL, /* init process */
67: NULL, /* init thread */
68: NULL, /* exit thread */
69: NULL, /* exit process */
70: NULL, /* exit master */
71: NGX_MODULE_V1_PADDING
72: };
73:
74:
75: static ngx_int_t
76: ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
77: {
78: ngx_event_t **index;
79:
80: if (event_index == NULL) {
81: FD_ZERO(&master_read_fd_set);
82: FD_ZERO(&master_write_fd_set);
83: nevents = 0;
84: }
85:
86: if (ngx_process >= NGX_PROCESS_WORKER
87: || cycle->old_cycle == NULL
88: || cycle->old_cycle->connection_n < cycle->connection_n)
89: {
90: index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
91: cycle->log);
92: if (index == NULL) {
93: return NGX_ERROR;
94: }
95:
96: if (event_index) {
97: ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
98: ngx_free(event_index);
99: }
100:
101: event_index = index;
102: }
103:
104: ngx_io = ngx_os_io;
105:
106: ngx_event_actions = ngx_select_module_ctx.actions;
107:
108: ngx_event_flags = NGX_USE_LEVEL_EVENT;
109:
110: max_read = 0;
111: max_write = 0;
112:
113: return NGX_OK;
114: }
115:
116:
117: static void
118: ngx_select_done(ngx_cycle_t *cycle)
119: {
120: ngx_free(event_index);
121:
122: event_index = NULL;
123: }
124:
125:
126: static ngx_int_t
127: ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
128: {
129: ngx_connection_t *c;
130:
131: c = ev->data;
132:
133: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
134: "select add event fd:%d ev:%i", c->fd, event);
135:
136: if (ev->index != NGX_INVALID_INDEX) {
137: ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
138: "select event fd:%d ev:%i is already set", c->fd, event);
139: return NGX_OK;
140: }
141:
142: if ((event == NGX_READ_EVENT && ev->write)
143: || (event == NGX_WRITE_EVENT && !ev->write))
144: {
145: ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
146: "invalid select %s event fd:%d ev:%i",
147: ev->write ? "write" : "read", c->fd, event);
148: return NGX_ERROR;
149: }
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: ev->active = 1;
170:
171: event_index[nevents] = ev;
172: ev->index = nevents;
173: nevents++;
174:
175: return NGX_OK;
176: }
177:
178:
179: static ngx_int_t
180: ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
181: {
182: ngx_event_t *e;
183: ngx_connection_t *c;
184:
185: c = ev->data;
186:
187: ev->active = 0;
188:
189: if (ev->index == NGX_INVALID_INDEX) {
190: return NGX_OK;
191: }
192:
193: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
194: "select del event fd:%d ev:%i", c->fd, event);
195:
196: if (event == NGX_READ_EVENT) {
197: FD_CLR(c->fd, &master_read_fd_set);
198: max_read--;
199:
200: } else if (event == NGX_WRITE_EVENT) {
201: FD_CLR(c->fd, &master_write_fd_set);
202: max_write--;
203: }
204:
205: if (ev->index < --nevents) {
206: e = event_index[nevents];
207: event_index[ev->index] = e;
208: e->index = ev->index;
209: }
210:
211: ev->index = NGX_INVALID_INDEX;
212:
213: return NGX_OK;
214: }
215:
216:
217: static ngx_int_t
218: ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
219: ngx_uint_t flags)
220: {
221: int ready, nready;
222: ngx_err_t err;
223: ngx_uint_t i, found;
224: ngx_event_t *ev, **queue;
225: struct timeval tv, *tp;
226: ngx_connection_t *c;
227:
228: #if (NGX_DEBUG)
229: if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
230: for (i = 0; i < nevents; i++) {
231: ev = event_index[i];
232: c = ev->data;
233: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
234: "select event: fd:%d wr:%d", c->fd, ev->write);
235: }
236: }
237: #endif
238:
239: if (timer == NGX_TIMER_INFINITE) {
240: tp = NULL;
241:
242: } else {
243: tv.tv_sec = (long) (timer / 1000);
244: tv.tv_usec = (long) ((timer % 1000) * 1000);
245: tp = &tv;
246: }
247:
248: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
249: "select timer: %M", timer);
250:
251: work_read_fd_set = master_read_fd_set;
252: work_write_fd_set = master_write_fd_set;
253:
254: if (max_read || max_write) {
255: ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
256:
257: } else {
258:
259: /*
260: * Winsock select() requires that at least one descriptor set must be
261: * be non-null, and any non-null descriptor set must contain at least
262: * one handle to a socket. Otherwise select() returns WSAEINVAL.
263: */
264:
265: ngx_msleep(timer);
266:
267: ready = 0;
268: }
269:
270: err = (ready == -1) ? ngx_socket_errno : 0;
271:
272: if (flags & NGX_UPDATE_TIME) {
273: ngx_time_update();
274: }
275:
276: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
277: "select ready %d", ready);
278:
279: if (err) {
280: ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
281:
282: if (err == WSAENOTSOCK) {
283: ngx_select_repair_fd_sets(cycle);
284: }
285:
286: return NGX_ERROR;
287: }
288:
289: if (ready == 0) {
290: if (timer != NGX_TIMER_INFINITE) {
291: return NGX_OK;
292: }
293:
294: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
295: "select() returned no events without timeout");
296: return NGX_ERROR;
297: }
298:
299: ngx_mutex_lock(ngx_posted_events_mutex);
300:
301: nready = 0;
302:
303: for (i = 0; i < nevents; i++) {
304: ev = event_index[i];
305: c = ev->data;
306: found = 0;
307:
308: if (ev->write) {
309: if (FD_ISSET(c->fd, &work_write_fd_set)) {
310: found = 1;
311: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
312: "select write %d", c->fd);
313: }
314:
315: } else {
316: if (FD_ISSET(c->fd, &work_read_fd_set)) {
317: found = 1;
318: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
319: "select read %d", c->fd);
320: }
321: }
322:
323: if (found) {
324: ev->ready = 1;
325:
326: queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
327: &ngx_posted_events);
328: ngx_locked_post_event(ev, queue);
329:
330: nready++;
331: }
332: }
333:
334: ngx_mutex_unlock(ngx_posted_events_mutex);
335:
336: if (ready != nready) {
337: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
338: "select ready != events: %d:%d", ready, nready);
339:
340: ngx_select_repair_fd_sets(cycle);
341: }
342:
343: return NGX_OK;
344: }
345:
346:
347: static void
348: ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
349: {
350: int n;
351: u_int i;
352: socklen_t len;
353: ngx_err_t err;
354: ngx_socket_t s;
355:
356: for (i = 0; i < master_read_fd_set.fd_count; i++) {
357:
358: s = master_read_fd_set.fd_array[i];
359: len = sizeof(int);
360:
361: if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
362: err = ngx_socket_errno;
363:
364: ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
365: "invalid descriptor #%d in read fd_set", s);
366:
367: FD_CLR(s, &master_read_fd_set);
368: }
369: }
370:
371: for (i = 0; i < master_write_fd_set.fd_count; i++) {
372:
373: s = master_write_fd_set.fd_array[i];
374: len = sizeof(int);
375:
376: if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
377: err = ngx_socket_errno;
378:
379: ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
380: "invalid descriptor #%d in write fd_set", s);
381:
382: FD_CLR(s, &master_write_fd_set);
383: }
384: }
385: }
386:
387:
388: static char *
389: ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
390: {
391: ngx_event_conf_t *ecf;
392:
393: ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
394:
395: if (ecf->use != ngx_select_module.ctx_index) {
396: return NGX_CONF_OK;
397: }
398:
399: return NGX_CONF_OK;
400: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>