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
);
263 err
= (ready
== -1) ? ngx_errno
: 0;
265 if (flags
& NGX_UPDATE_TIME
|| ngx_event_timer_alarm
) {
269 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
270 "poll ready %d of %d", ready
, nevents
);
273 if (err
== NGX_EINTR
) {
275 if (ngx_event_timer_alarm
) {
276 ngx_event_timer_alarm
= 0;
280 level
= NGX_LOG_INFO
;
283 level
= NGX_LOG_ALERT
;
286 ngx_log_error(level
, cycle
->log
, err
, "poll() failed");
291 if (timer
!= NGX_TIMER_INFINITE
) {
295 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
296 "poll() returned no events without timeout");
300 ngx_mutex_lock(ngx_posted_events_mutex
);
304 for (i
= 0; i
< nevents
&& ready
; i
++) {
306 revents
= event_list
[i
].revents
;
309 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
310 "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
311 i
, event_list
[i
].fd
, event_list
[i
].events
, revents
);
314 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
315 "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
316 i
, event_list
[i
].fd
, event_list
[i
].events
, revents
);
320 if (revents
& POLLNVAL
) {
321 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
322 "poll() error fd:%d ev:%04Xd rev:%04Xd",
323 event_list
[i
].fd
, event_list
[i
].events
, revents
);
326 if (revents
& ~(POLLIN
|POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
)) {
327 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
328 "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
329 event_list
[i
].fd
, event_list
[i
].events
, revents
);
332 if (event_list
[i
].fd
== -1) {
334 * the disabled event, a workaround for our possible bug,
335 * see the comment below
340 c
= ngx_cycle
->files
[event_list
[i
].fd
];
343 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0, "unexpected event");
346 * it is certainly our fault and it should be investigated,
347 * in the meantime we disable this event to avoid a CPU spinning
350 if (i
== nevents
- 1) {
353 event_list
[i
].fd
= -1;
359 if ((revents
& (POLLERR
|POLLHUP
|POLLNVAL
))
360 && (revents
& (POLLIN
|POLLOUT
)) == 0)
363 * if the error events were returned without POLLIN or POLLOUT,
364 * then add these flags to handle the events at least in one
368 revents
|= POLLIN
|POLLOUT
;
373 if (revents
& POLLIN
) {
378 if ((flags
& NGX_POST_THREAD_EVENTS
) && !ev
->accept
) {
379 ev
->posted_ready
= 1;
385 queue
= (ngx_event_t
**) (ev
->accept
? &ngx_posted_accept_events
:
387 ngx_locked_post_event(ev
, queue
);
390 if (revents
& POLLOUT
) {
394 if (flags
& NGX_POST_THREAD_EVENTS
) {
395 ev
->posted_ready
= 1;
401 ngx_locked_post_event(ev
, &ngx_posted_events
);
410 ngx_mutex_unlock(ngx_posted_events_mutex
);
413 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0, "poll ready != events");
421 ngx_poll_init_conf(ngx_cycle_t
*cycle
, void *conf
)
423 ngx_event_conf_t
*ecf
;
425 ecf
= ngx_event_get_conf(cycle
->conf_ctx
, ngx_event_core_module
);
427 if (ecf
->use
!= ngx_poll_module
.ctx_index
) {
433 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, 0,
434 "poll() is not supported in the threaded mode");
435 return NGX_CONF_ERROR
;