Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_sigio_module.c @ 246:6753e8cdaa2c
nginx-0.0.1-2004-01-30-20:39:00 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 30 Jan 2004 17:39:00 +0000 |
parents | 50186b49f2ad |
children | 008276b9e061 |
comparison
equal
deleted
inserted
replaced
245:e6c005b66b3a | 246:6753e8cdaa2c |
---|---|
1 | 1 |
2 | 2 /* |
3 int ngx_sigio_add_event(ngx_event_t *ev, int signal) | 3 * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/ |
4 { | 4 */ |
5 ngx_connection_t *c; | 5 |
6 | 6 |
7 c = (ngx_connection_t *) ev->data; | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 | |
11 | |
12 #if (TEST_BUILD_SIGIO) | |
13 | |
14 #define F_SETSIG 10 | |
15 | |
16 #endif | |
17 | |
18 | |
19 typedef struct { | |
20 int signal; | |
21 } ngx_sigio_conf_t; | |
22 | |
23 | |
24 static int ngx_sigio_init(ngx_cycle_t *cycle); | |
25 static void ngx_sigio_done(ngx_cycle_t *cycle); | |
26 static int ngx_sigio_add_event(ngx_event_t *ev, int event, u_int flags); | |
27 static int ngx_sigio_del_event(ngx_event_t *ev, int event, u_int flags); | |
28 static int ngx_sigio_add_connection(ngx_connection_t *c); | |
29 static int ngx_sigio_del_connection(ngx_connection_t *c); | |
30 static int ngx_sigio_process_events(ngx_log_t *log); | |
31 | |
32 static void *ngx_sigio_create_conf(ngx_cycle_t *cycle); | |
33 static char *ngx_sigio_init_conf(ngx_cycle_t *cycle, void *conf); | |
34 | |
35 | |
36 static sigset_t set; | |
37 | |
38 | |
39 static ngx_str_t sigio_name = ngx_string("sigio"); | |
40 | |
41 static ngx_command_t ngx_sigio_commands[] = { | |
42 | |
43 {ngx_string("sigio_signal"), | |
44 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
45 ngx_conf_set_num_slot, | |
46 0, | |
47 offsetof(ngx_sigio_conf_t, signal), | |
48 NULL}, | |
49 | |
50 ngx_null_command | |
51 }; | |
52 | |
53 | |
54 ngx_event_module_t ngx_sigio_module_ctx = { | |
55 &sigio_name, | |
56 ngx_sigio_create_conf, /* create configuration */ | |
57 ngx_sigio_init_conf, /* init configuration */ | |
58 | |
59 { | |
60 ngx_sigio_add_event, /* add an event */ | |
61 ngx_sigio_del_event, /* delete an event */ | |
62 ngx_sigio_add_event, /* enable an event */ | |
63 ngx_sigio_del_event, /* disable an event */ | |
64 ngx_sigio_add_connection, /* add an connection */ | |
65 ngx_sigio_del_connection, /* delete an connection */ | |
66 ngx_sigio_process_events, /* process the events */ | |
67 ngx_sigio_init, /* init the events */ | |
68 ngx_sigio_done, /* done the events */ | |
69 } | |
70 | |
71 }; | |
72 | |
73 ngx_module_t ngx_sigio_module = { | |
74 NGX_MODULE, | |
75 &ngx_sigio_module_ctx, /* module context */ | |
76 ngx_sigio_commands, /* module directives */ | |
77 NGX_EVENT_MODULE, /* module type */ | |
78 NULL, /* init module */ | |
79 NULL /* init child */ | |
80 }; | |
81 | |
82 | |
83 static int ngx_sigio_init(ngx_cycle_t *cycle) | |
84 { | |
85 ngx_sigio_conf_t *sgcf; | |
86 | |
87 sgcf = ngx_event_get_conf(cycle->conf_ctx, ngx_sigio_module); | |
88 | |
89 sigemptyset(&set); | |
90 sigaddset(&set, sgcf->signal); | |
91 sigaddset(&set, SIGIO); | |
92 | |
93 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { | |
94 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
95 "sigprocmask() failed"); | |
96 return NGX_ERROR; | |
97 } | |
98 | |
99 ngx_io = ngx_os_io; | |
100 | |
101 ngx_event_actions = ngx_sigio_module_ctx.actions; | |
102 | |
103 ngx_event_flags = NGX_USE_SIGIO_EVENT; | |
104 | |
105 return NGX_OK; | |
106 } | |
107 | |
108 | |
109 static void ngx_sigio_done(ngx_cycle_t *cycle) | |
110 { | |
111 } | |
112 | |
113 | |
114 static int ngx_sigio_add_event(ngx_event_t *ev, int event, u_int flags) | |
115 { | |
116 ngx_connection_t *c; | |
117 | |
118 c = ev->data; | |
119 | |
120 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
121 "sigio add event: fd:%d ev:%04X", c->fd, event); | |
122 | |
123 return NGX_OK; | |
124 } | |
125 | |
126 | |
127 static int ngx_sigio_del_event(ngx_event_t *ev, int event, u_int flags) | |
128 { | |
129 ngx_connection_t *c; | |
130 | |
131 c = ev->data; | |
132 | |
133 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
134 "sigio del event: fd:%d ev:%04X", c->fd, event); | |
135 | |
136 return NGX_OK; | |
137 } | |
138 | |
139 | |
140 static int ngx_sigio_add_connection(ngx_connection_t *c) | |
141 { | |
142 ngx_sigio_conf_t *sgcf; | |
143 | |
144 sgcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_sigio_module); | |
145 | |
146 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
147 "sigio add connection: fd:%d signo:%d", c->fd, sgcf->signal); | |
8 | 148 |
9 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) { | 149 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) { |
10 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 150 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, |
11 "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed"); | 151 "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed"); |
12 return NGX_ERROR; | 152 return NGX_ERROR; |
13 } | 153 } |
14 | 154 |
15 if (fcntl(c->fd, F_SETSIG, signal) == -1) { | 155 if (fcntl(c->fd, F_SETSIG, sgcf->signal) == -1) { |
16 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 156 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, |
17 "fcntl(F_SETSIG) failed"); | 157 "fcntl(F_SETSIG) failed"); |
18 return NGX_ERROR; | 158 return NGX_ERROR; |
19 } | 159 } |
20 | 160 |
21 if (fcntl(c->fd, F_SETOWN, pid) == -1) { | 161 if (fcntl(c->fd, F_SETOWN, ngx_getpid()) == -1) { |
22 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 162 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, |
23 "fcntl(F_SETOWN) failed"); | 163 "fcntl(F_SETOWN) failed"); |
24 return NGX_ERROR; | 164 return NGX_ERROR; |
25 } | 165 } |
26 | 166 |
27 #if (HAVE_ONESIGFD) | 167 #if (HAVE_ONESIGFD) |
28 if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) { | 168 if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) { |
29 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 169 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, |
30 "fcntl(F_SETAUXFL) failed"); | 170 "fcntl(F_SETAUXFL) failed"); |
31 return NGX_ERROR; | 171 return NGX_ERROR; |
32 } | 172 } |
33 #endif | 173 #endif |
34 | 174 |
35 return NGX_OK; | 175 c->read->active = 1; |
36 } | 176 c->write->active = 1; |
177 | |
178 return NGX_OK; | |
179 } | |
180 | |
181 | |
182 static int ngx_sigio_del_connection(ngx_connection_t *c) | |
183 { | |
184 c->read->active = 0; | |
185 c->write->active = 0; | |
186 | |
187 return NGX_OK; | |
188 } | |
189 | |
37 | 190 |
38 int ngx_sigio_process_events(ngx_log_t *log) | 191 int ngx_sigio_process_events(ngx_log_t *log) |
39 { | 192 { |
40 struct siginfo si; | 193 int signo; |
41 | 194 ngx_int_t instance, i; |
42 for ( ;; ) { | 195 size_t n; |
43 if (timer) { | 196 ngx_msec_t timer; |
44 sig = sigtimedwait(&sigio_set, &si, &ts); | 197 ngx_err_t err; |
45 | 198 ngx_cycle_t **cycle; |
46 if (sig == -1) { | 199 siginfo_t si; |
47 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 200 struct timeval tv; |
48 "sigtimedwait() failed"); | 201 struct timespec ts; |
202 ngx_connection_t *c; | |
203 ngx_epoch_msec_t delta; | |
204 ngx_sigio_conf_t *sgcf; | |
205 | |
206 timer = ngx_event_find_timer(); | |
207 ngx_old_elapsed_msec = ngx_elapsed_msec; | |
208 | |
209 if (timer) { | |
210 ts.tv_sec = timer / 1000; | |
211 ts.tv_nsec = (timer % 1000) * 1000000; | |
212 } | |
213 | |
214 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "sigio timer: %d", timer); | |
215 | |
216 if (timer) { | |
217 signo = sigtimedwait(&set, &si, &ts); | |
218 } else { | |
219 signo = sigwaitinfo(&set, &si); | |
220 } | |
221 | |
222 if (signo == -1) { | |
223 err = ngx_errno; | |
224 } else { | |
225 err = 0; | |
226 } | |
227 | |
228 ngx_gettimeofday(&tv); | |
229 ngx_time_update(tv.tv_sec); | |
230 | |
231 delta = ngx_elapsed_msec; | |
232 ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; | |
233 | |
234 if (err == -1) { | |
235 ngx_log_error(NGX_LOG_ALERT, c->log, err, | |
236 timer ? "sigtimedwait() failed" : "sigwaitinfo() failed"); | |
237 return NGX_ERROR; | |
238 } | |
239 | |
240 if (timer) { | |
241 delta = ngx_elapsed_msec - delta; | |
242 | |
243 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, | |
244 "sigio timer: %d, delta: %d", timer, (int) delta); | |
245 } | |
246 | |
247 sgcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_sigio_module); | |
248 | |
249 if (signo == sgcf->signal) { | |
250 | |
251 /* STUB: old_cycles */ | |
252 c = &ngx_connections[si.si_fd]; | |
253 | |
254 if (si.si_band & EPOLLIN) { | |
255 if (!c->read->active) { | |
49 continue; | 256 continue; |
50 } | 257 } |
51 } | 258 |
52 | 259 c->read->ready = 1; |
53 } else { | 260 c->read->event_handler(c->read); |
54 sig = sigwaitinfo(&set, &si); | 261 } |
55 | 262 |
56 if (sig == -1) { | 263 } else if (signo == SIGIO) { |
57 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 264 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
58 "sigwaitinfo() failed"); | 265 "signal queue overflowed: " |
266 "SIGIO, fd:%d, band:%d", si.si_fd, si.si_band); | |
267 | |
268 } else { | |
269 ngx_log_error(NGX_LOG_ALERT, log, 0, | |
270 timer ? "sigtimedwait() returned unexpected signal: %d": | |
271 "sigwaitinfo() returned unexpected signal: %d", | |
272 signo); | |
273 return NGX_ERROR; | |
274 } | |
275 } | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 for (i = 0; i < events; i++) { | |
283 c = event_list[i].data.ptr; | |
284 | |
285 instance = (uintptr_t) c & 1; | |
286 c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); | |
287 | |
288 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, | |
289 "sigio: fd:%d ev:%04X d:" PTR_FMT, | |
290 c->fd, event_list[i].events, event_list[i].data); | |
291 | |
292 if (c->read->instance != instance) { | |
293 | |
294 /* | |
295 * it's a stale event from a file descriptor | |
296 * that was just closed in this iteration | |
297 */ | |
298 | |
299 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
300 "sigio: stale event " PTR_FMT, c); | |
301 continue; | |
302 } | |
303 | |
304 if (event_list[i].events & EPOLLOUT) { | |
305 if (!c->write->active) { | |
306 continue; | |
59 } | 307 } |
60 } | 308 |
61 | 309 c->write->ready = 1; |
62 if (sig == rtsig) { | 310 c->write->event_handler(c->write); |
63 c = &ngx_connections[si.si_fd]; | 311 } |
64 | 312 |
65 if (si.si_band & (POLLERR|POLLHUP|POLLNVAL)) { | 313 if (event_list[i].events & (EPOLLERR|EPOLLHUP)) { |
66 ev = ???; | 314 ngx_log_error(NGX_LOG_ALERT, log, 0, |
67 | 315 "sigio_wait() error on fd:%d ev:%d", |
68 if (ev->active) { | 316 c->fd, event_list[i].events); |
69 ev->ready = 1; | 317 continue; |
70 if (ev->event_handler(ev) == NGX_ERROR) { | 318 } |
71 ev->close_handler(ev); | 319 |
72 } | 320 if (event_list[i].events & ~(EPOLLIN|EPOLLOUT)) { |
73 } | 321 ngx_log_error(NGX_LOG_ALERT, log, 0, |
74 } | 322 "sigio_wait() returned strange events on fd:%d ev:%d", |
75 | 323 c->fd, event_list[i].events); |
76 if (si.si_band & (POLLIN)) { | 324 } |
77 ev = c->read; | 325 |
78 | 326 } |
79 if (ev->active) { | 327 |
80 ev->ready = 1; | 328 if (timer != (ngx_msec_t) -1 && delta) { |
81 if (ev->event_handler(ev) == NGX_ERROR) { | 329 ngx_event_expire_timers((ngx_msec_t) delta); |
82 ev->close_handler(ev); | 330 } |
83 } | 331 |
84 } | 332 return NGX_OK; |
85 } | 333 } |
86 | 334 |
87 if (si.si_band & (POLLOUT)) { | 335 |
88 ev = c->write; | 336 static void *ngx_sigio_create_conf(ngx_cycle_t *cycle) |
89 | 337 { |
90 if (ev->active) { | 338 ngx_sigio_conf_t *sgcf; |
91 ev->ready = 1; | 339 |
92 if (ev->event_handler(ev) == NGX_ERROR) { | 340 ngx_test_null(sgcf, ngx_palloc(cycle->pool, sizeof(ngx_sigio_conf_t)), |
93 ev->close_handler(ev); | 341 NGX_CONF_ERROR); |
94 } | 342 |
95 } | 343 sgcf->events = NGX_CONF_UNSET; |
96 } | 344 |
97 | 345 return epcf; |
98 } else if (sig == SIGIO) { | 346 } |
99 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | 347 |
100 "Signal queue overflowed: " | 348 |
101 "SIGIO, fd:%d, band:%d", si.si_fd, si.si_band); | 349 static char *ngx_sigio_init_conf(ngx_cycle_t *cycle, void *conf) |
102 | 350 { |
103 /* flush queue: method #1 (dphttpd) */ | 351 ngx_sigio_conf_t *sgcf = conf; |
104 ts.tv_sec = 0; | 352 |
105 ts.tv_nsec = 0; | 353 ngx_conf_init_unsigned_value(sgcf->signal, SIGRTMIN); |
106 while (sigtimedwait(&sigio_set, &si, &ts) > 0); | 354 |
107 | 355 return NGX_CONF_OK; |
108 /* flush queue: method #2 (dkftpbench) */ | 356 } |
109 signal(m_signum, SIG_IGN); | |
110 signal(m_signum, SIG_DFL); | |
111 | |
112 /* do poll */ | |
113 | |
114 } else { | |
115 } | |
116 } | |
117 } |