3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static ngx_int_t
ngx_poll_init(ngx_cycle_t
*cycle
, ngx_msec_t timer
);
13 static void ngx_poll_done(ngx_cycle_t
*cycle
);
14 static ngx_int_t
ngx_poll_add_event(ngx_event_t
*ev
, ngx_int_t event
,
16 static ngx_int_t
ngx_poll_del_event(ngx_event_t
*ev
, ngx_int_t event
,
18 static ngx_int_t
ngx_poll_process_events(ngx_cycle_t
*cycle
, ngx_msec_t timer
,
20 static char *ngx_poll_init_conf(ngx_cycle_t
*cycle
, void *conf
);
23 static struct pollfd
*event_list
;
24 static ngx_int_t nevents
;
27 static ngx_str_t poll_name
= ngx_string("poll");
29 ngx_event_module_t ngx_poll_module_ctx
= {
31 NULL
, /* create configuration */
32 ngx_poll_init_conf
, /* init configuration */
35 ngx_poll_add_event
, /* add an event */
36 ngx_poll_del_event
, /* delete an event */
37 ngx_poll_add_event
, /* enable an event */
38 ngx_poll_del_event
, /* disable an event */
39 NULL
, /* add an connection */
40 NULL
, /* delete an connection */
41 NULL
, /* process the changes */
42 ngx_poll_process_events
, /* process the events */
43 ngx_poll_init
, /* init the events */
44 ngx_poll_done
/* done the events */
49 ngx_module_t ngx_poll_module
= {
51 &ngx_poll_module_ctx
, /* module context */
52 NULL
, /* module directives */
53 NGX_EVENT_MODULE
, /* module type */
54 NULL
, /* init master */
55 NULL
, /* init module */
56 NULL
, /* init process */
57 NULL
, /* init thread */
58 NULL
, /* exit thread */
59 NULL
, /* exit process */
60 NULL
, /* exit master */
67 ngx_poll_init(ngx_cycle_t
*cycle
, ngx_msec_t timer
)
71 if (event_list
== NULL
) {
75 if (ngx_process
== NGX_PROCESS_WORKER
76 || cycle
->old_cycle
== NULL
77 || cycle
->old_cycle
->connection_n
< cycle
->connection_n
)
79 list
= ngx_alloc(sizeof(struct pollfd
) * cycle
->connection_n
,
86 ngx_memcpy(list
, event_list
, sizeof(ngx_event_t
*) * nevents
);
95 ngx_event_actions
= ngx_poll_module_ctx
.actions
;
97 ngx_event_flags
= NGX_USE_LEVEL_EVENT
|NGX_USE_FD_EVENT
;
104 ngx_poll_done(ngx_cycle_t
*cycle
)
106 ngx_free(event_list
);
113 ngx_poll_add_event(ngx_event_t
*ev
, ngx_int_t event
, ngx_uint_t flags
)
122 if (ev
->index
!= NGX_INVALID_INDEX
) {
123 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, 0,
124 "poll event fd:%d ev:%i is already set", c
->fd
, event
);
128 if (event
== NGX_READ_EVENT
) {
130 #if (NGX_READ_EVENT != POLLIN)
136 #if (NGX_WRITE_EVENT != POLLOUT)
141 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
142 "poll add event: fd:%d ev:%i", c
->fd
, event
);
144 if (e
== NULL
|| e
->index
== NGX_INVALID_INDEX
) {
145 event_list
[nevents
].fd
= c
->fd
;
146 event_list
[nevents
].events
= (short) event
;
147 event_list
[nevents
].revents
= 0;
153 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
154 "poll add index: %i", e
->index
);
156 event_list
[e
->index
].events
|= (short) event
;
157 ev
->index
= e
->index
;
165 ngx_poll_del_event(ngx_event_t
*ev
, ngx_int_t event
, ngx_uint_t flags
)
174 if (ev
->index
== NGX_INVALID_INDEX
) {
175 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, 0,
176 "poll event fd:%d ev:%i is already deleted",
181 if (event
== NGX_READ_EVENT
) {
183 #if (NGX_READ_EVENT != POLLIN)
189 #if (NGX_WRITE_EVENT != POLLOUT)
194 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
195 "poll del event: fd:%d ev:%i", c
->fd
, event
);
197 if (e
== NULL
|| e
->index
== NGX_INVALID_INDEX
) {
200 if (ev
->index
< (ngx_uint_t
) nevents
) {
202 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
203 "index: copy event %ui to %i", nevents
, ev
->index
);
205 event_list
[ev
->index
] = event_list
[nevents
];
207 c
= ngx_cycle
->files
[event_list
[nevents
].fd
];
210 ngx_log_error(NGX_LOG_ALERT
, ev
->log
, 0,
211 "unexpected last event");
214 if (c
->read
->index
== (ngx_uint_t
) nevents
) {
215 c
->read
->index
= ev
->index
;
218 if (c
->write
->index
== (ngx_uint_t
) nevents
) {
219 c
->write
->index
= ev
->index
;
225 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
226 "poll del index: %i", e
->index
);
228 event_list
[e
->index
].events
&= (short) ~event
;
231 ev
->index
= NGX_INVALID_INDEX
;
238 ngx_poll_process_events(ngx_cycle_t
*cycle
, ngx_msec_t timer
, ngx_uint_t flags
)
243 ngx_uint_t found
, level
;
244 ngx_event_t
*ev
, **queue
;
247 /* NGX_TIMER_INFINITE == INFTIM */
250 if (cycle
->log
->log_level
& NGX_LOG_DEBUG_ALL
) {
251 for (i
= 0; i
< nevents
; i
++) {
252 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
253 "poll: %d: fd:%d ev:%04Xd",
254 i
, event_list
[i
].fd
, event_list
[i
].events
);
259 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0, "poll timer: %M", timer
);
261 ready
= poll(event_list
, (u_int
) nevents
, (int) timer
);
269 if (flags
& NGX_UPDATE_TIME
|| ngx_event_timer_alarm
) {
273 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
274 "poll ready %d of %d", ready
, nevents
);
277 if (err
== NGX_EINTR
) {
279 if (ngx_event_timer_alarm
) {
280 ngx_event_timer_alarm
= 0;
284 level
= NGX_LOG_INFO
;
287 level
= NGX_LOG_ALERT
;
290 ngx_log_error(level
, cycle
->log
, err
, "poll() failed");
295 if (timer
!= NGX_TIMER_INFINITE
) {
299 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
300 "poll() returned no events without timeout");
304 ngx_mutex_lock(ngx_posted_events_mutex
);
308 for (i
= 0; i
< nevents
&& ready
; i
++) {
310 revents
= event_list
[i
].revents
;
313 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
314 "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
315 i
, event_list
[i
].fd
, event_list
[i
].events
, revents
);
318 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
319 "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
320 i
, event_list
[i
].fd
, event_list
[i
].events
, revents
);
324 if (revents
& POLLNVAL
) {
325 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
326 "poll() error fd:%d ev:%04Xd rev:%04Xd",
327 event_list
[i
].fd
, event_list
[i
].events
, revents
);
330 if (revents
& ~(POLLIN
|POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
)) {
331 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
332 "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
333 event_list
[i
].fd
, event_list
[i
].events
, revents
);
336 if (event_list
[i
].fd
== -1) {
338 * the disabled event, a workaround for our possible bug,
339 * see the comment below
344 c
= ngx_cycle
->files
[event_list
[i
].fd
];
347 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0, "unexpected event");
350 * it is certainly our fault and it should be investigated,
351 * in the meantime we disable this event to avoid a CPU spinning
354 if (i
== nevents
- 1) {
357 event_list
[i
].fd
= -1;
363 if ((revents
& (POLLERR
|POLLHUP
|POLLNVAL
))
364 && (revents
& (POLLIN
|POLLOUT
)) == 0)
367 * if the error events were returned without POLLIN or POLLOUT,
368 * then add these flags to handle the events at least in one
372 revents
|= POLLIN
|POLLOUT
;
377 if (revents
& POLLIN
) {
382 if ((flags
& NGX_POST_THREAD_EVENTS
) && !ev
->accept
) {
383 ev
->posted_ready
= 1;
389 queue
= (ngx_event_t
**) (ev
->accept
? &ngx_posted_accept_events
:
391 ngx_locked_post_event(ev
, queue
);
394 if (revents
& POLLOUT
) {
398 if (flags
& NGX_POST_THREAD_EVENTS
) {
399 ev
->posted_ready
= 1;
405 ngx_locked_post_event(ev
, &ngx_posted_events
);
414 ngx_mutex_unlock(ngx_posted_events_mutex
);
417 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0, "poll ready != events");
425 ngx_poll_init_conf(ngx_cycle_t
*cycle
, void *conf
)
427 ngx_event_conf_t
*ecf
;
429 ecf
= ngx_event_get_conf(cycle
->conf_ctx
, ngx_event_core_module
);
431 if (ecf
->use
!= ngx_poll_module
.ctx_index
) {
437 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, 0,
438 "poll() is not supported in the threaded mode");
439 return NGX_CONF_ERROR
;