Mercurial > hg > nginx
annotate src/event/modules/ngx_eventport_module.c @ 7349:f6047a579ca1
gRPC: improved keepalive handling.
The code is now able to parse additional control frames after
the response is received, and can send control frames as well.
This fixes keepalive problems as observed with grpc-c, which can
send window update and ping frames after the response, see
http://mailman.nginx.org/pipermail/nginx/2018-August/056620.html.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 03 Sep 2018 19:34:01 +0300 |
parents | cbf59d483c9c |
children | 3c51385e5da1 |
rev | line source |
---|---|
719 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
719 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_event.h> | |
11 | |
12 | |
13 #if (NGX_TEST_BUILD_EVENTPORT) | |
14 | |
15 #define ushort_t u_short | |
16 #define uint_t u_int | |
17 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
18 #ifndef CLOCK_REALTIME |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
19 #define CLOCK_REALTIME 0 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
20 typedef int clockid_t; |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
21 typedef void * timer_t; |
7189
cbf59d483c9c
Fixed --test-build-eventport on macOS 10.12 and later.
Ruslan Ermilov <ru@nginx.com>
parents:
6923
diff
changeset
|
22 #elif (NGX_DARWIN) |
cbf59d483c9c
Fixed --test-build-eventport on macOS 10.12 and later.
Ruslan Ermilov <ru@nginx.com>
parents:
6923
diff
changeset
|
23 typedef void * timer_t; |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
24 #endif |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
25 |
719 | 26 /* Solaris declarations */ |
27 | |
28 #define PORT_SOURCE_AIO 1 | |
29 #define PORT_SOURCE_TIMER 2 | |
30 #define PORT_SOURCE_USER 3 | |
31 #define PORT_SOURCE_FD 4 | |
32 #define PORT_SOURCE_ALERT 5 | |
33 #define PORT_SOURCE_MQ 6 | |
34 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
35 #ifndef ETIME |
719 | 36 #define ETIME 64 |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
37 #endif |
719 | 38 |
39 #define SIGEV_PORT 4 | |
40 | |
41 typedef struct { | |
42 int portev_events; /* event data is source specific */ | |
43 ushort_t portev_source; /* event source */ | |
44 ushort_t portev_pad; /* port internal use */ | |
45 uintptr_t portev_object; /* source specific object */ | |
46 void *portev_user; /* user cookie */ | |
47 } port_event_t; | |
48 | |
49 typedef struct port_notify { | |
50 int portnfy_port; /* bind request(s) to port */ | |
51 void *portnfy_user; /* user defined */ | |
52 } port_notify_t; | |
53 | |
6475
7d6970ba5209
Events: fixed test building with eventport on OS X.
Ruslan Ermilov <ru@nginx.com>
parents:
6447
diff
changeset
|
54 #if (__FreeBSD__ && __FreeBSD_version < 700005) || (NGX_DARWIN) |
1939
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
55 |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
56 typedef struct itimerspec { /* definition per POSIX.4 */ |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
57 struct timespec it_interval;/* timer period */ |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
58 struct timespec it_value; /* timer expiration */ |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
59 } itimerspec_t; |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
60 |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
61 #endif |
6e7daf852eec
restore building --test-build-rtsig and --test-build-eventport on FreeBSD 6
Igor Sysoev <igor@sysoev.ru>
parents:
1870
diff
changeset
|
62 |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
63 int port_create(void); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
64 |
719 | 65 int port_create(void) |
66 { | |
67 return -1; | |
68 } | |
69 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
70 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
71 int port_associate(int port, int source, uintptr_t object, int events, |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
72 void *user); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
73 |
719 | 74 int port_associate(int port, int source, uintptr_t object, int events, |
75 void *user) | |
76 { | |
77 return -1; | |
78 } | |
79 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
80 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
81 int port_dissociate(int port, int source, uintptr_t object); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
82 |
719 | 83 int port_dissociate(int port, int source, uintptr_t object) |
84 { | |
85 return -1; | |
86 } | |
87 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
88 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
89 int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
90 struct timespec *timeout); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
91 |
719 | 92 int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, |
93 struct timespec *timeout) | |
94 { | |
95 return -1; | |
96 } | |
97 | |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
98 int port_send(int port, int events, void *user); |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
99 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
100 int port_send(int port, int events, void *user) |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
101 { |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
102 return -1; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
103 } |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
104 |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
105 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
106 int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
107 |
719 | 108 int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid) |
109 { | |
110 return -1; | |
111 } | |
112 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
113 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
114 int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
115 struct itimerspec *ovalue); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
116 |
719 | 117 int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, |
118 struct itimerspec *ovalue) | |
119 { | |
120 return -1; | |
121 } | |
122 | |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
123 |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
124 int timer_delete(timer_t timerid); |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4572
diff
changeset
|
125 |
719 | 126 int timer_delete(timer_t timerid) |
127 { | |
128 return -1; | |
129 } | |
130 | |
131 #endif | |
132 | |
133 | |
134 typedef struct { | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
135 ngx_uint_t events; |
719 | 136 } ngx_eventport_conf_t; |
137 | |
138 | |
139 static ngx_int_t ngx_eventport_init(ngx_cycle_t *cycle, ngx_msec_t timer); | |
140 static void ngx_eventport_done(ngx_cycle_t *cycle); | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
141 static ngx_int_t ngx_eventport_add_event(ngx_event_t *ev, ngx_int_t event, |
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
142 ngx_uint_t flags); |
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
143 static ngx_int_t ngx_eventport_del_event(ngx_event_t *ev, ngx_int_t event, |
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
144 ngx_uint_t flags); |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
145 static ngx_int_t ngx_eventport_notify(ngx_event_handler_pt handler); |
719 | 146 static ngx_int_t ngx_eventport_process_events(ngx_cycle_t *cycle, |
147 ngx_msec_t timer, ngx_uint_t flags); | |
148 | |
149 static void *ngx_eventport_create_conf(ngx_cycle_t *cycle); | |
150 static char *ngx_eventport_init_conf(ngx_cycle_t *cycle, void *conf); | |
151 | |
152 static int ep = -1; | |
153 static port_event_t *event_list; | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
154 static ngx_uint_t nevents; |
1870
a62fb6c156c5
fix building --test-build-rtsig and --test-build-eventport on FreeBSD 7
Igor Sysoev <igor@sysoev.ru>
parents:
1354
diff
changeset
|
155 static timer_t event_timer = (timer_t) -1; |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
156 static ngx_event_t notify_event; |
719 | 157 |
158 static ngx_str_t eventport_name = ngx_string("eventport"); | |
159 | |
160 | |
161 static ngx_command_t ngx_eventport_commands[] = { | |
162 | |
163 { ngx_string("eventport_events"), | |
164 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
165 ngx_conf_set_num_slot, | |
166 0, | |
167 offsetof(ngx_eventport_conf_t, events), | |
168 NULL }, | |
169 | |
170 ngx_null_command | |
171 }; | |
172 | |
173 | |
6922
a72886067bbb
Added missing static specifiers.
Eran Kornblau <erankor@gmail.com>
parents:
6806
diff
changeset
|
174 static ngx_event_module_t ngx_eventport_module_ctx = { |
719 | 175 &eventport_name, |
176 ngx_eventport_create_conf, /* create configuration */ | |
177 ngx_eventport_init_conf, /* init configuration */ | |
178 | |
179 { | |
180 ngx_eventport_add_event, /* add an event */ | |
181 ngx_eventport_del_event, /* delete an event */ | |
182 ngx_eventport_add_event, /* enable an event */ | |
183 ngx_eventport_del_event, /* disable an event */ | |
184 NULL, /* add an connection */ | |
185 NULL, /* delete an connection */ | |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
186 ngx_eventport_notify, /* trigger a notify */ |
719 | 187 ngx_eventport_process_events, /* process the events */ |
188 ngx_eventport_init, /* init the events */ | |
189 ngx_eventport_done, /* done the events */ | |
190 } | |
191 | |
192 }; | |
193 | |
194 ngx_module_t ngx_eventport_module = { | |
195 NGX_MODULE_V1, | |
196 &ngx_eventport_module_ctx, /* module context */ | |
197 ngx_eventport_commands, /* module directives */ | |
198 NGX_EVENT_MODULE, /* module type */ | |
199 NULL, /* init master */ | |
200 NULL, /* init module */ | |
201 NULL, /* init process */ | |
202 NULL, /* init thread */ | |
203 NULL, /* exit thread */ | |
204 NULL, /* exit process */ | |
205 NULL, /* exit master */ | |
206 NGX_MODULE_V1_PADDING | |
207 }; | |
208 | |
209 | |
210 static ngx_int_t | |
211 ngx_eventport_init(ngx_cycle_t *cycle, ngx_msec_t timer) | |
212 { | |
213 port_notify_t pn; | |
214 struct itimerspec its; | |
215 struct sigevent sev; | |
216 ngx_eventport_conf_t *epcf; | |
217 | |
218 epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_eventport_module); | |
219 | |
220 if (ep == -1) { | |
221 ep = port_create(); | |
222 | |
223 if (ep == -1) { | |
224 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
225 "port_create() failed"); | |
226 return NGX_ERROR; | |
227 } | |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
228 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
229 notify_event.active = 1; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
230 notify_event.log = cycle->log; |
719 | 231 } |
232 | |
233 if (nevents < epcf->events) { | |
234 if (event_list) { | |
235 ngx_free(event_list); | |
236 } | |
237 | |
238 event_list = ngx_alloc(sizeof(port_event_t) * epcf->events, | |
239 cycle->log); | |
240 if (event_list == NULL) { | |
241 return NGX_ERROR; | |
242 } | |
243 } | |
244 | |
245 ngx_event_flags = NGX_USE_EVENTPORT_EVENT; | |
246 | |
247 if (timer) { | |
248 ngx_memzero(&pn, sizeof(port_notify_t)); | |
249 pn.portnfy_port = ep; | |
250 | |
251 ngx_memzero(&sev, sizeof(struct sigevent)); | |
252 sev.sigev_notify = SIGEV_PORT; | |
253 #if !(NGX_TEST_BUILD_EVENTPORT) | |
254 sev.sigev_value.sival_ptr = &pn; | |
255 #endif | |
256 | |
257 if (timer_create(CLOCK_REALTIME, &sev, &event_timer) == -1) { | |
258 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
259 "timer_create() failed"); | |
260 return NGX_ERROR; | |
261 } | |
262 | |
263 its.it_interval.tv_sec = timer / 1000; | |
264 its.it_interval.tv_nsec = (timer % 1000) * 1000000; | |
265 its.it_value.tv_sec = timer / 1000; | |
266 its.it_value.tv_nsec = (timer % 1000) * 1000000; | |
267 | |
268 if (timer_settime(event_timer, 0, &its, NULL) == -1) { | |
269 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
270 "timer_settime() failed"); | |
271 return NGX_ERROR; | |
272 } | |
273 | |
274 ngx_event_flags |= NGX_USE_TIMER_EVENT; | |
275 } | |
276 | |
277 nevents = epcf->events; | |
278 | |
279 ngx_io = ngx_os_io; | |
280 | |
281 ngx_event_actions = ngx_eventport_module_ctx.actions; | |
282 | |
283 return NGX_OK; | |
284 } | |
285 | |
286 | |
287 static void | |
288 ngx_eventport_done(ngx_cycle_t *cycle) | |
289 { | |
1870
a62fb6c156c5
fix building --test-build-rtsig and --test-build-eventport on FreeBSD 7
Igor Sysoev <igor@sysoev.ru>
parents:
1354
diff
changeset
|
290 if (event_timer != (timer_t) -1) { |
719 | 291 if (timer_delete(event_timer) == -1) { |
292 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
293 "timer_delete() failed"); | |
294 } | |
295 | |
1870
a62fb6c156c5
fix building --test-build-rtsig and --test-build-eventport on FreeBSD 7
Igor Sysoev <igor@sysoev.ru>
parents:
1354
diff
changeset
|
296 event_timer = (timer_t) -1; |
719 | 297 } |
298 | |
299 if (close(ep) == -1) { | |
300 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
301 "close() event port failed"); | |
302 } | |
303 | |
304 ep = -1; | |
305 | |
306 ngx_free(event_list); | |
307 | |
308 event_list = NULL; | |
309 nevents = 0; | |
310 } | |
311 | |
312 | |
313 static ngx_int_t | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
314 ngx_eventport_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) |
719 | 315 { |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
316 ngx_int_t events, prev; |
719 | 317 ngx_event_t *e; |
318 ngx_connection_t *c; | |
319 | |
320 c = ev->data; | |
321 | |
322 events = event; | |
323 | |
324 if (event == NGX_READ_EVENT) { | |
325 e = c->write; | |
326 prev = POLLOUT; | |
327 #if (NGX_READ_EVENT != POLLIN) | |
328 events = POLLIN; | |
329 #endif | |
330 | |
331 } else { | |
332 e = c->read; | |
333 prev = POLLIN; | |
334 #if (NGX_WRITE_EVENT != POLLOUT) | |
335 events = POLLOUT; | |
336 #endif | |
337 } | |
338 | |
339 if (e->oneshot) { | |
340 events |= prev; | |
341 } | |
342 | |
343 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
344 "eventport add event: fd:%d ev:%04Xi", c->fd, events); |
719 | 345 |
346 if (port_associate(ep, PORT_SOURCE_FD, c->fd, events, | |
347 (void *) ((uintptr_t) ev | ev->instance)) | |
348 == -1) | |
349 { | |
350 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
351 "port_associate() failed"); | |
352 return NGX_ERROR; | |
353 } | |
354 | |
355 ev->active = 1; | |
356 ev->oneshot = 1; | |
357 | |
358 return NGX_OK; | |
359 } | |
360 | |
361 | |
362 static ngx_int_t | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
363 ngx_eventport_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) |
719 | 364 { |
365 ngx_event_t *e; | |
366 ngx_connection_t *c; | |
367 | |
368 /* | |
369 * when the file descriptor is closed, the event port automatically | |
4572
67653855682e
Fixed spelling in multiline C comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
370 * dissociates it from the port, so we do not need to dissociate explicitly |
719 | 371 * the event before the closing the file descriptor |
372 */ | |
373 | |
374 if (flags & NGX_CLOSE_EVENT) { | |
375 ev->active = 0; | |
376 ev->oneshot = 0; | |
377 return NGX_OK; | |
378 } | |
379 | |
380 c = ev->data; | |
381 | |
382 if (event == NGX_READ_EVENT) { | |
383 e = c->write; | |
384 event = POLLOUT; | |
385 | |
386 } else { | |
387 e = c->read; | |
388 event = POLLIN; | |
389 } | |
390 | |
391 if (e->oneshot) { | |
392 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
393 "eventport change event: fd:%d ev:%04Xi", c->fd, event); |
719 | 394 |
395 if (port_associate(ep, PORT_SOURCE_FD, c->fd, event, | |
396 (void *) ((uintptr_t) ev | ev->instance)) | |
397 == -1) | |
398 { | |
399 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
400 "port_associate() failed"); | |
401 return NGX_ERROR; | |
402 } | |
403 | |
404 } else { | |
405 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
406 "eventport del event: fd:%d", c->fd); | |
407 | |
408 if (port_dissociate(ep, PORT_SOURCE_FD, c->fd) == -1) { | |
409 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
410 "port_dissociate() failed"); | |
411 return NGX_ERROR; | |
412 } | |
413 } | |
414 | |
415 ev->active = 0; | |
416 ev->oneshot = 0; | |
417 | |
418 return NGX_OK; | |
419 } | |
420 | |
421 | |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
422 static ngx_int_t |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
423 ngx_eventport_notify(ngx_event_handler_pt handler) |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
424 { |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
425 notify_event.handler = handler; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
426 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
427 if (port_send(ep, 0, ¬ify_event) != 0) { |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
428 ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno, |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
429 "port_send() failed"); |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
430 return NGX_ERROR; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
431 } |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
432 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
433 return NGX_OK; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
434 } |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
435 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
436 |
6923
fbdaad9b0e7b
Added missing "static" specifiers found by gcc -Wtraditional.
Ruslan Ermilov <ru@nginx.com>
parents:
6922
diff
changeset
|
437 static ngx_int_t |
719 | 438 ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, |
439 ngx_uint_t flags) | |
440 { | |
441 int n, revents; | |
442 u_int events; | |
443 ngx_err_t err; | |
444 ngx_int_t instance; | |
445 ngx_uint_t i, level; | |
5821
3f5f0ab59b35
Events: processing of posted events changed from LIFO to FIFO.
Valentin Bartenev <vbart@nginx.com>
parents:
5820
diff
changeset
|
446 ngx_event_t *ev, *rev, *wev; |
3f5f0ab59b35
Events: processing of posted events changed from LIFO to FIFO.
Valentin Bartenev <vbart@nginx.com>
parents:
5820
diff
changeset
|
447 ngx_queue_t *queue; |
719 | 448 ngx_connection_t *c; |
449 struct timespec ts, *tp; | |
450 | |
451 if (timer == NGX_TIMER_INFINITE) { | |
452 tp = NULL; | |
453 | |
454 } else { | |
455 ts.tv_sec = timer / 1000; | |
456 ts.tv_nsec = (timer % 1000) * 1000000; | |
457 tp = &ts; | |
458 } | |
459 | |
460 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
461 "eventport timer: %M", timer); | |
462 | |
463 events = 1; | |
464 | |
1354
f69d1aab6a0f
make 64-bit ngx_int_t on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
1287
diff
changeset
|
465 n = port_getn(ep, event_list, (u_int) nevents, &events, tp); |
719 | 466 |
467 err = ngx_errno; | |
468 | |
469 if (flags & NGX_UPDATE_TIME) { | |
3475
ab353d7dc182
*) introduce ngx_time_sigsafe_update() to update the error log time only
Igor Sysoev <igor@sysoev.ru>
parents:
3474
diff
changeset
|
470 ngx_time_update(); |
719 | 471 } |
472 | |
473 if (n == -1) { | |
474 if (err == ETIME) { | |
475 if (timer != NGX_TIMER_INFINITE) { | |
476 return NGX_OK; | |
477 } | |
478 | |
479 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
480 "port_getn() returned no events without timeout"); | |
481 return NGX_ERROR; | |
482 } | |
483 | |
484 level = (err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT; | |
485 ngx_log_error(level, cycle->log, err, "port_getn() failed"); | |
486 return NGX_ERROR; | |
487 } | |
488 | |
489 if (events == 0) { | |
490 if (timer != NGX_TIMER_INFINITE) { | |
491 return NGX_OK; | |
492 } | |
493 | |
494 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
495 "port_getn() returned no events without timeout"); | |
496 return NGX_ERROR; | |
497 } | |
498 | |
499 for (i = 0; i < events; i++) { | |
500 | |
501 if (event_list[i].portev_source == PORT_SOURCE_TIMER) { | |
3475
ab353d7dc182
*) introduce ngx_time_sigsafe_update() to update the error log time only
Igor Sysoev <igor@sysoev.ru>
parents:
3474
diff
changeset
|
502 ngx_time_update(); |
719 | 503 continue; |
504 } | |
505 | |
506 ev = event_list[i].portev_user; | |
507 | |
508 switch (event_list[i].portev_source) { | |
509 | |
510 case PORT_SOURCE_FD: | |
511 | |
512 instance = (uintptr_t) ev & 1; | |
513 ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1); | |
514 | |
515 if (ev->closed || ev->instance != instance) { | |
516 | |
517 /* | |
518 * the stale event from a file descriptor | |
519 * that was just closed in this iteration | |
520 */ | |
521 | |
522 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
523 "eventport: stale event %p", ev); | |
524 continue; | |
525 } | |
526 | |
527 revents = event_list[i].portev_events; | |
528 | |
529 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
530 "eventport: fd:%d, ev:%04Xd", | |
6479
dc92298b1852
Events: fixed logging.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6475
diff
changeset
|
531 (int) event_list[i].portev_object, revents); |
719 | 532 |
533 if (revents & (POLLERR|POLLHUP|POLLNVAL)) { | |
1128
06479b01caff
decrease log level from alert to debug for POLLERR|POLLHUP|POLLNVAL
Igor Sysoev <igor@sysoev.ru>
parents:
929
diff
changeset
|
534 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
06479b01caff
decrease log level from alert to debug for POLLERR|POLLHUP|POLLNVAL
Igor Sysoev <igor@sysoev.ru>
parents:
929
diff
changeset
|
535 "port_getn() error fd:%d ev:%04Xd", |
6479
dc92298b1852
Events: fixed logging.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6475
diff
changeset
|
536 (int) event_list[i].portev_object, revents); |
719 | 537 } |
538 | |
539 if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { | |
540 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
541 "strange port_getn() events fd:%d ev:%04Xd", | |
6479
dc92298b1852
Events: fixed logging.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6475
diff
changeset
|
542 (int) event_list[i].portev_object, revents); |
719 | 543 } |
544 | |
6806
75dbab4ea930
Events: improved error event handling for UDP sockets.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6479
diff
changeset
|
545 if (revents & (POLLERR|POLLHUP|POLLNVAL)) { |
75dbab4ea930
Events: improved error event handling for UDP sockets.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6479
diff
changeset
|
546 |
719 | 547 /* |
6806
75dbab4ea930
Events: improved error event handling for UDP sockets.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6479
diff
changeset
|
548 * if the error events were returned, add POLLIN and POLLOUT |
75dbab4ea930
Events: improved error event handling for UDP sockets.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6479
diff
changeset
|
549 * to handle the events at least in one active handler |
719 | 550 */ |
551 | |
552 revents |= POLLIN|POLLOUT; | |
553 } | |
554 | |
555 c = ev->data; | |
556 rev = c->read; | |
557 wev = c->write; | |
558 | |
559 rev->active = 0; | |
560 wev->active = 0; | |
561 | |
562 if (revents & POLLIN) { | |
5820
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
563 rev->ready = 1; |
719 | 564 |
565 if (flags & NGX_POST_EVENTS) { | |
5820
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
566 queue = rev->accept ? &ngx_posted_accept_events |
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
567 : &ngx_posted_events; |
719 | 568 |
5820
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
569 ngx_post_event(rev, queue); |
719 | 570 |
571 } else { | |
572 rev->handler(rev); | |
1287
3dd9883fa121
fix segfault when event port returns POLLERR without POLLIN or POLLOUT
Igor Sysoev <igor@sysoev.ru>
parents:
1128
diff
changeset
|
573 |
5170
6362bd26e4b0
Events: protection from stale events in eventport and devpoll.
Valentin Bartenev <vbart@nginx.com>
parents:
4759
diff
changeset
|
574 if (ev->closed || ev->instance != instance) { |
1287
3dd9883fa121
fix segfault when event port returns POLLERR without POLLIN or POLLOUT
Igor Sysoev <igor@sysoev.ru>
parents:
1128
diff
changeset
|
575 continue; |
3dd9883fa121
fix segfault when event port returns POLLERR without POLLIN or POLLOUT
Igor Sysoev <igor@sysoev.ru>
parents:
1128
diff
changeset
|
576 } |
719 | 577 } |
578 | |
579 if (rev->accept) { | |
580 if (ngx_use_accept_mutex) { | |
581 ngx_accept_events = 1; | |
582 continue; | |
583 } | |
584 | |
585 if (port_associate(ep, PORT_SOURCE_FD, c->fd, POLLIN, | |
586 (void *) ((uintptr_t) ev | ev->instance)) | |
587 == -1) | |
588 { | |
589 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
590 "port_associate() failed"); | |
591 return NGX_ERROR; | |
592 } | |
593 } | |
594 } | |
595 | |
596 if (revents & POLLOUT) { | |
5820
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
597 wev->ready = 1; |
719 | 598 |
599 if (flags & NGX_POST_EVENTS) { | |
5820
3377f9459e99
Events: removed broken thread support from posted events.
Valentin Bartenev <vbart@nginx.com>
parents:
5175
diff
changeset
|
600 ngx_post_event(wev, &ngx_posted_events); |
719 | 601 |
602 } else { | |
603 wev->handler(wev); | |
604 } | |
605 } | |
606 | |
607 continue; | |
608 | |
6021
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
609 case PORT_SOURCE_USER: |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
610 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
611 ev->handler(ev); |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
612 |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
613 continue; |
117c77b22db1
Events: implemented eventport notification mechanism.
Ruslan Ermilov <ru@nginx.com>
parents:
6018
diff
changeset
|
614 |
719 | 615 default: |
616 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
6005
d84f0abd4a53
Events: fixed typo in the error message.
Ruslan Ermilov <ru@nginx.com>
parents:
5821
diff
changeset
|
617 "unexpected eventport object %d", |
6479
dc92298b1852
Events: fixed logging.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6475
diff
changeset
|
618 (int) event_list[i].portev_object); |
719 | 619 continue; |
620 } | |
621 } | |
622 | |
623 return NGX_OK; | |
624 } | |
625 | |
626 | |
627 static void * | |
628 ngx_eventport_create_conf(ngx_cycle_t *cycle) | |
629 { | |
630 ngx_eventport_conf_t *epcf; | |
631 | |
632 epcf = ngx_palloc(cycle->pool, sizeof(ngx_eventport_conf_t)); | |
633 if (epcf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
1939
diff
changeset
|
634 return NULL; |
719 | 635 } |
636 | |
637 epcf->events = NGX_CONF_UNSET; | |
638 | |
639 return epcf; | |
640 } | |
641 | |
642 | |
643 static char * | |
644 ngx_eventport_init_conf(ngx_cycle_t *cycle, void *conf) | |
645 { | |
646 ngx_eventport_conf_t *epcf = conf; | |
647 | |
648 ngx_conf_init_uint_value(epcf->events, 32); | |
649 | |
650 return NGX_CONF_OK; | |
651 } |