Mercurial > hg > nginx
comparison src/core/nginx.c @ 218:05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 05 Jan 2004 20:55:48 +0000 |
parents | c5d1cdcb04ec |
children | f57597ec5249 |
comparison
equal
deleted
inserted
replaced
217:c5d1cdcb04ec | 218:05592fd7a436 |
---|---|
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_event.h> | 4 #include <ngx_event.h> |
5 #include <nginx.h> | 5 #include <nginx.h> |
6 | 6 |
7 | 7 |
8 /* STUB */ | 8 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); |
9 void stub_init(ngx_cycle_t *cycle); | 9 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); |
10 | 10 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle); |
11 | |
12 | |
13 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle, ngx_log_t *log); | |
14 static int ngx_open_listening_sockets(ngx_cycle_t *cycle, ngx_log_t *log); | |
15 static void ngx_clean_old_cycles(ngx_event_t *ev); | |
16 | 11 |
17 | 12 |
18 typedef struct { | 13 typedef struct { |
14 ngx_str_t user; | |
19 int daemon; | 15 int daemon; |
16 int single; | |
20 ngx_str_t pid; | 17 ngx_str_t pid; |
21 } ngx_core_conf_t; | 18 } ngx_core_conf_t; |
22 | 19 |
23 | 20 |
24 static ngx_str_t core_name = ngx_string("core"); | 21 static ngx_str_t core_name = ngx_string("core"); |
25 | 22 |
26 static ngx_command_t ngx_core_commands[] = { | 23 static ngx_command_t ngx_core_commands[] = { |
24 | |
25 { ngx_string("user"), | |
26 NGX_MAIN_CONF|NGX_CONF_TAKE1, | |
27 ngx_conf_set_core_str_slot, | |
28 0, | |
29 offsetof(ngx_core_conf_t, user), | |
30 NULL }, | |
27 | 31 |
28 { ngx_string("daemon"), | 32 { ngx_string("daemon"), |
29 NGX_MAIN_CONF|NGX_CONF_TAKE1, | 33 NGX_MAIN_CONF|NGX_CONF_TAKE1, |
30 ngx_conf_set_core_flag_slot, | 34 ngx_conf_set_core_flag_slot, |
31 0, | 35 0, |
32 offsetof(ngx_core_conf_t, daemon), | 36 offsetof(ngx_core_conf_t, daemon), |
33 NULL }, | 37 NULL }, |
34 | 38 |
39 { ngx_string("single_process"), | |
40 NGX_MAIN_CONF|NGX_CONF_TAKE1, | |
41 ngx_conf_set_core_flag_slot, | |
42 0, | |
43 offsetof(ngx_core_conf_t, single), | |
44 NULL }, | |
45 | |
35 ngx_null_command | 46 ngx_null_command |
36 }; | 47 }; |
37 | 48 |
38 | 49 |
39 ngx_module_t ngx_core_module = { | 50 ngx_module_t ngx_core_module = { |
40 NGX_MODULE, | 51 NGX_MODULE, |
41 &core_name, /* module context */ | 52 &core_name, /* module context */ |
42 ngx_core_commands, /* module directives */ | 53 ngx_core_commands, /* module directives */ |
43 NGX_CORE_MODULE, /* module type */ | 54 NGX_CORE_MODULE, /* module type */ |
44 NULL, /* init module */ | 55 ngx_core_module_init, /* init module */ |
45 NULL /* init child */ | 56 NULL /* init child */ |
46 }; | 57 }; |
47 | 58 |
48 | 59 |
49 int ngx_max_module; | 60 ngx_int_t ngx_max_module; |
50 ngx_os_io_t ngx_io; | 61 |
51 | 62 |
52 volatile ngx_cycle_t *ngx_cycle; | 63 /* STUB */ |
53 ngx_array_t ngx_old_cycles; | 64 uid_t user; |
54 | |
55 static ngx_pool_t *ngx_temp_pool; | |
56 static ngx_event_t ngx_cleaner_event; | |
57 | |
58 | |
59 /* STUB NAME */ | |
60 static ngx_connection_t dumb; | |
61 | 65 |
62 u_int ngx_connection_counter; | 66 u_int ngx_connection_counter; |
63 | 67 |
64 | 68 ngx_int_t ngx_master; |
65 int done; | 69 ngx_int_t ngx_single; |
66 int restart; | 70 |
67 int rotate; | 71 |
68 | 72 ngx_int_t ngx_respawn; |
69 | 73 ngx_int_t ngx_terminate; |
70 int main(int argc, char *const *argv) | 74 ngx_int_t ngx_quit; |
75 ngx_int_t ngx_reconfigure; | |
76 ngx_int_t ngx_reopen; | |
77 ngx_int_t ngx_change_binary; | |
78 | |
79 | |
80 int main(int argc, char *const *argv, char **envp) | |
71 { | 81 { |
72 int i; | 82 struct timeval tv; |
73 ngx_fd_t fd; | 83 ngx_fd_t fd; |
74 ngx_log_t *log; | 84 ngx_int_t i; |
75 ngx_cycle_t *cycle, init_cycle; | 85 ngx_err_t err; |
76 ngx_open_file_t *file; | 86 ngx_log_t *log; |
87 ngx_cycle_t *cycle, init_cycle; | |
88 ngx_open_file_t *file; | |
89 ngx_core_conf_t *ccf; | |
77 #if !(WIN32) | 90 #if !(WIN32) |
78 size_t len; | 91 size_t len; |
79 char pid[/* STUB */ 10]; | 92 char pid[/* STUB */ 10]; |
80 ngx_file_t pidfile; | 93 ngx_file_t pidfile; |
81 ngx_core_conf_t *ccf; | 94 struct passwd *pwd; |
82 #endif | 95 #endif |
83 | 96 |
84 #if __FreeBSD__ | 97 #if __FreeBSD__ |
85 ngx_debug_init(); | 98 ngx_debug_init(); |
86 #endif | 99 #endif |
92 ngx_regex_init(); | 105 ngx_regex_init(); |
93 #endif | 106 #endif |
94 | 107 |
95 log = ngx_log_init_errlog(); | 108 log = ngx_log_init_errlog(); |
96 | 109 |
97 | |
98 /* init_cycle->log is required for signal handlers */ | 110 /* init_cycle->log is required for signal handlers */ |
99 | 111 |
100 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); | 112 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); |
101 init_cycle.log = log; | 113 init_cycle.log = log; |
102 ngx_cycle = &init_cycle; | 114 ngx_cycle = &init_cycle; |
108 ngx_max_module = 0; | 120 ngx_max_module = 0; |
109 for (i = 0; ngx_modules[i]; i++) { | 121 for (i = 0; ngx_modules[i]; i++) { |
110 ngx_modules[i]->index = ngx_max_module++; | 122 ngx_modules[i]->index = ngx_max_module++; |
111 } | 123 } |
112 | 124 |
113 cycle = ngx_init_cycle(NULL, log); | 125 if (!(init_cycle.pool = ngx_create_pool(1024, log))) { |
126 return 1; | |
127 } | |
128 | |
129 if (ngx_set_inherited_sockets(&init_cycle, envp) == NGX_ERROR) { | |
130 return 1; | |
131 } | |
132 | |
133 cycle = ngx_init_cycle(&init_cycle); | |
114 if (cycle == NULL) { | 134 if (cycle == NULL) { |
115 return 1; | 135 return 1; |
116 } | 136 } |
117 | 137 |
118 ngx_cycle = cycle; | 138 ngx_cycle = cycle; |
119 | 139 |
140 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | |
141 | |
142 if (ccf->single == 1) { | |
143 ngx_master = 0; | |
144 ngx_single = 1; | |
145 | |
146 } else { | |
147 ngx_master = 1; | |
148 ngx_single = 0; | |
149 } | |
150 | |
120 #if !(WIN32) | 151 #if !(WIN32) |
121 | 152 |
122 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | 153 /* STUB */ |
154 if (ccf->user.len) { | |
155 pwd = getpwnam(ccf->user.data); | |
156 if (pwd == NULL) { | |
157 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
158 "getpwnam(%s) failed", ccf->user); | |
159 return 1; | |
160 } | |
161 | |
162 user = pwd->pw_uid; | |
163 } | |
164 /* */ | |
123 | 165 |
124 if (ccf->daemon != 0) { | 166 if (ccf->daemon != 0) { |
125 if (ngx_daemon(cycle->log) == NGX_ERROR) { | 167 if (ngx_daemon(cycle->log) == NGX_ERROR) { |
126 return 1; | 168 return 1; |
127 } | 169 } |
160 ngx_close_file_n " \"%s\" failed", pidfile.name.data); | 202 ngx_close_file_n " \"%s\" failed", pidfile.name.data); |
161 } | 203 } |
162 | 204 |
163 #endif | 205 #endif |
164 | 206 |
165 /* life cycle */ | 207 /* a life cycle */ |
166 | 208 |
167 for ( ;; ) { | 209 for ( ;; ) { |
210 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "new cycle"); | |
211 | |
212 if (ngx_master) { | |
213 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, | |
214 "worker process", NGX_PROCESS_RESPAWN); | |
215 | |
216 } else { | |
217 ngx_init_temp_number(); | |
218 | |
219 for (i = 0; ngx_modules[i]; i++) { | |
220 if (ngx_modules[i]->init_process) { | |
221 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
222 /* fatal */ | |
223 exit(1); | |
224 } | |
225 } | |
226 } | |
227 } | |
228 | |
168 #if 0 | 229 #if 0 |
169 /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG|NGX_LOG_DEBUG_HTTP; | 230 reconfigure = 0; |
231 reopen = 0; | |
170 #endif | 232 #endif |
171 | 233 |
172 #if 0 | 234 /* a cycle with the same configuration */ |
173 | |
174 #if !(WIN32) | |
175 ngx_spawn_process(cycle->log); | |
176 #endif | |
177 | |
178 stub_init(cycle); | |
179 #endif | |
180 | |
181 /* TODO: forks */ | |
182 | |
183 ngx_init_temp_number(); | |
184 | |
185 for (i = 0; ngx_modules[i]; i++) { | |
186 if (ngx_modules[i]->init_child) { | |
187 if (ngx_modules[i]->init_child(cycle) == NGX_ERROR) { | |
188 /* fatal */ | |
189 exit(1); | |
190 } | |
191 } | |
192 } | |
193 | |
194 /* TODO: threads */ | |
195 | |
196 restart = 0; | |
197 rotate = 0; | |
198 | 235 |
199 for ( ;; ) { | 236 for ( ;; ) { |
200 | 237 |
238 /* an event loop */ | |
239 | |
201 for ( ;; ) { | 240 for ( ;; ) { |
202 ngx_log_debug(cycle->log, "worker cycle"); | 241 |
203 | 242 err = 0; |
204 ngx_process_events(cycle->log); | 243 |
205 | 244 if (ngx_single) { |
206 if (done) { | 245 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
246 "worker cycle"); | |
247 | |
248 ngx_process_events(cycle->log); | |
249 | |
250 } else { | |
251 ngx_set_errno(0); | |
252 ngx_msleep(1000); | |
253 err = ngx_errno; | |
254 | |
255 ngx_gettimeofday(&tv); | |
256 ngx_time_update(tv.tv_sec); | |
257 | |
258 if (err) { | |
259 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, err, | |
260 "sleep() exited"); | |
261 } | |
262 } | |
263 | |
264 if (ngx_quit || ngx_terminate) { | |
207 #if !(WIN32) | 265 #if !(WIN32) |
208 if (ngx_delete_file(pidfile.name.data) == NGX_FILE_ERROR) { | 266 if (ngx_delete_file(pidfile.name.data) == NGX_FILE_ERROR) { |
209 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 267 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
210 ngx_delete_file_n " \"%s\" failed", | 268 ngx_delete_file_n " \"%s\" failed", |
211 pidfile.name.data); | 269 pidfile.name.data); |
212 } | 270 } |
213 #endif | 271 #endif |
214 | 272 |
215 ngx_log_error(NGX_LOG_INFO, | 273 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); |
216 cycle->log, 0, "exiting"); | 274 |
275 if (ngx_master) { | |
276 ngx_signal_processes(cycle, | |
277 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); | |
278 | |
279 /* TODO: wait workers */ | |
280 | |
281 ngx_msleep(1000); | |
282 | |
283 ngx_gettimeofday(&tv); | |
284 ngx_time_update(tv.tv_sec); | |
285 } | |
286 | |
287 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exit"); | |
217 exit(0); | 288 exit(0); |
218 } | 289 } |
219 | 290 |
220 if (rotate) { | 291 if (err == NGX_EINTR) { |
221 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | 292 ngx_respawn_processes(cycle); |
222 | 293 } |
223 file = cycle->open_files.elts; | 294 |
224 for (i = 0; i < cycle->open_files.nelts; i++) { | 295 if (ngx_change_binary) { |
225 if (file[i].name.data == NULL) { | 296 ngx_change_binary = 0; |
226 continue; | 297 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, |
227 } | 298 "changing binary"); |
228 | 299 ngx_exec_new_binary(cycle, argv); |
229 fd = ngx_open_file(file[i].name.data, | 300 /* TODO: quit workers */ |
230 NGX_FILE_RDWR, | 301 } |
231 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); | 302 |
232 | 303 if (ngx_reconfigure) { |
233 ngx_log_debug(log, "REOPEN: %d:%d:%s" _ fd _ file[i].fd _ file[i].name.data); | 304 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reconfiguring"); |
234 | |
235 if (fd == NGX_INVALID_FILE) { | |
236 ngx_log_error(NGX_LOG_EMERG, | |
237 cycle->log, ngx_errno, | |
238 ngx_open_file_n " \"%s\" failed", | |
239 file[i].name.data); | |
240 continue; | |
241 } | |
242 | |
243 #if (WIN32) | |
244 if (ngx_file_append_mode(fd) == NGX_ERROR) { | |
245 ngx_log_error(NGX_LOG_EMERG, | |
246 cycle->log, ngx_errno, | |
247 ngx_file_append_mode_n | |
248 " \"%s\" failed", | |
249 file[i].name.data); | |
250 | |
251 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
252 ngx_log_error(NGX_LOG_EMERG, | |
253 cycle->log, ngx_errno, | |
254 ngx_close_file_n " \"%s\" failed", | |
255 file[i].name.data); | |
256 } | |
257 | |
258 continue; | |
259 } | |
260 #endif | |
261 | |
262 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { | |
263 ngx_log_error(NGX_LOG_EMERG, | |
264 cycle->log, ngx_errno, | |
265 ngx_close_file_n " \"%s\" failed", | |
266 file[i].name.data); | |
267 } | |
268 | |
269 file[i].fd = fd; | |
270 } | |
271 | |
272 rotate = 0; | |
273 } | |
274 | |
275 if (restart) { | |
276 ngx_log_debug(cycle->log, "restart"); | |
277 break; | 305 break; |
278 } | 306 } |
279 | 307 |
280 } | 308 if (ngx_reopen) { |
281 | 309 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, |
282 cycle = ngx_init_cycle(cycle, cycle->log); | 310 "reopening logs"); |
311 ngx_reopen_files(cycle); | |
312 ngx_reopen = 0; | |
313 } | |
314 | |
315 } | |
316 | |
317 cycle = ngx_init_cycle(cycle); | |
283 if (cycle == NULL) { | 318 if (cycle == NULL) { |
284 cycle = (ngx_cycle_t *) ngx_cycle; | 319 cycle = (ngx_cycle_t *) ngx_cycle; |
285 continue; | 320 continue; |
286 } | 321 } |
287 | 322 |
288 ngx_cycle = cycle; | 323 ngx_cycle = cycle; |
324 ngx_reconfigure = 0; | |
289 break; | 325 break; |
290 } | 326 } |
291 } | 327 } |
292 } | 328 } |
293 | 329 |
294 | 330 #if 0 |
295 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle, ngx_log_t *log) | 331 |
332 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) | |
296 { | 333 { |
297 int i, n, failed; | 334 ngx_int_t i, n, failed; |
298 ngx_str_t conf_file; | 335 ngx_str_t conf_file; |
336 ngx_log_t *log; | |
299 ngx_conf_t conf; | 337 ngx_conf_t conf; |
300 ngx_pool_t *pool; | 338 ngx_pool_t *pool; |
301 ngx_cycle_t *cycle, **old; | 339 ngx_cycle_t *cycle, **old; |
302 ngx_socket_t fd; | 340 ngx_socket_t fd; |
303 ngx_core_conf_t *ccf; | 341 ngx_core_conf_t *ccf; |
304 ngx_open_file_t *file; | 342 ngx_open_file_t *file; |
305 ngx_listening_t *ls, *nls; | 343 ngx_listening_t *ls, *nls; |
306 | 344 |
345 log = old_cycle->log; | |
307 | 346 |
308 if (!(pool = ngx_create_pool(16 * 1024, log))) { | 347 if (!(pool = ngx_create_pool(16 * 1024, log))) { |
309 return NULL; | 348 return NULL; |
310 } | 349 } |
311 | 350 |
316 cycle->pool = pool; | 355 cycle->pool = pool; |
317 | 356 |
318 cycle->old_cycle = old_cycle; | 357 cycle->old_cycle = old_cycle; |
319 | 358 |
320 | 359 |
321 n = old_cycle ? old_cycle->pathes.nelts : 10; | 360 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10; |
322 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) { | 361 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) { |
323 ngx_destroy_pool(pool); | 362 ngx_destroy_pool(pool); |
324 return NULL; | 363 return NULL; |
325 } | 364 } |
326 cycle->pathes.nelts = 0; | 365 cycle->pathes.nelts = 0; |
327 cycle->pathes.size = sizeof(ngx_path_t *); | 366 cycle->pathes.size = sizeof(ngx_path_t *); |
328 cycle->pathes.nalloc = n; | 367 cycle->pathes.nalloc = n; |
329 cycle->pathes.pool = pool; | 368 cycle->pathes.pool = pool; |
330 | 369 |
331 | 370 |
332 n = old_cycle ? old_cycle->open_files.nelts : 20; | 371 n = old_cycle->open_files.nelts ? old_cycle->open_files.nelts : 20; |
333 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t)); | 372 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t)); |
334 if (cycle->open_files.elts == NULL) { | 373 if (cycle->open_files.elts == NULL) { |
335 ngx_destroy_pool(pool); | 374 ngx_destroy_pool(pool); |
336 return NULL; | 375 return NULL; |
337 } | 376 } |
345 ngx_destroy_pool(pool); | 384 ngx_destroy_pool(pool); |
346 return NULL; | 385 return NULL; |
347 } | 386 } |
348 | 387 |
349 | 388 |
350 n = old_cycle ? old_cycle->listening.nelts : 10; | 389 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; |
351 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); | 390 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); |
352 if (cycle->listening.elts == NULL) { | 391 if (cycle->listening.elts == NULL) { |
353 ngx_destroy_pool(pool); | 392 ngx_destroy_pool(pool); |
354 return NULL; | 393 return NULL; |
355 } | 394 } |
373 /* set by pcalloc() | 412 /* set by pcalloc() |
374 * | 413 * |
375 * ccf->pid = NULL; | 414 * ccf->pid = NULL; |
376 */ | 415 */ |
377 ccf->daemon = -1; | 416 ccf->daemon = -1; |
417 ccf->single = -1; | |
378 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf; | 418 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf; |
379 | 419 |
380 | 420 |
381 ngx_memzero(&conf, sizeof(ngx_conf_t)); | 421 ngx_memzero(&conf, sizeof(ngx_conf_t)); |
382 /* STUB: init array ? */ | 422 /* STUB: init array ? */ |
433 break; | 473 break; |
434 } | 474 } |
435 #endif | 475 #endif |
436 } | 476 } |
437 | 477 |
438 #if 0 | |
439 /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG; | |
440 #endif | |
441 | |
442 if (!failed) { | 478 if (!failed) { |
443 if (old_cycle) { | 479 if (old_cycle->listening.nelts) { |
444 ls = old_cycle->listening.elts; | 480 ls = old_cycle->listening.elts; |
445 for (i = 0; i < old_cycle->listening.nelts; i++) { | 481 for (i = 0; i < old_cycle->listening.nelts; i++) { |
446 ls[i].remain = 0; | 482 ls[i].remain = 0; |
447 } | 483 } |
448 | 484 |
449 nls = cycle->listening.elts; | 485 nls = cycle->listening.elts; |
450 for (n = 0; n < cycle->listening.nelts; n++) { | 486 for (n = 0; n < cycle->listening.nelts; n++) { |
451 for (i = 0; i < old_cycle->listening.nelts; i++) { | 487 for (i = 0; i < old_cycle->listening.nelts; i++) { |
488 if (ls[i].ignore) { | |
489 continue; | |
490 } | |
491 | |
492 ngx_log_error(NGX_LOG_INFO, log, 0, | |
493 "%X, %X", | |
494 *(int *) ls[i].sockaddr, | |
495 *(int *) nls[n].sockaddr); | |
496 | |
452 if (ngx_memcmp(nls[n].sockaddr, | 497 if (ngx_memcmp(nls[n].sockaddr, |
453 ls[i].sockaddr, ls[i].socklen) == 0) | 498 ls[i].sockaddr, ls[i].socklen) == 0) |
454 { | 499 { |
455 fd = ls[i].fd; | 500 fd = ls[i].fd; |
456 #if (WIN32) | 501 #if (WIN32) |
490 ls[i].new = 1; | 535 ls[i].new = 1; |
491 } | 536 } |
492 } | 537 } |
493 | 538 |
494 if (!failed) { | 539 if (!failed) { |
495 if (ngx_open_listening_sockets(cycle, log) == NGX_ERROR) { | 540 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) { |
496 failed = 1; | 541 failed = 1; |
497 } | 542 } |
498 } | 543 } |
499 } | 544 } |
500 | 545 |
534 | 579 |
535 /* commit the new cycle configuration */ | 580 /* commit the new cycle configuration */ |
536 | 581 |
537 pool->log = cycle->log; | 582 pool->log = cycle->log; |
538 | 583 |
539 #if 1 | |
540 /* STUB */ cycle->one_process = 1; | |
541 #endif | |
542 | 584 |
543 for (i = 0; ngx_modules[i]; i++) { | 585 for (i = 0; ngx_modules[i]; i++) { |
544 if (ngx_modules[i]->init_module) { | 586 if (ngx_modules[i]->init_module) { |
545 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) { | 587 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) { |
546 /* fatal */ | 588 /* fatal */ |
547 exit(1); | 589 exit(1); |
548 } | 590 } |
549 } | 591 } |
550 } | 592 } |
551 | 593 |
552 if (old_cycle == NULL) { | 594 /* close and delete stuff that lefts from an old cycle */ |
553 return cycle; | 595 |
554 } | 596 /* close the unneeded listening sockets */ |
555 | 597 |
556 ls = old_cycle->listening.elts; | 598 ls = old_cycle->listening.elts; |
557 for (i = 0; i < old_cycle->listening.nelts; i++) { | 599 for (i = 0; i < old_cycle->listening.nelts; i++) { |
558 if (ls[i].remain) { | 600 if (ls[i].remain) { |
559 continue; | 601 continue; |
564 ngx_close_socket_n " %s failed", | 606 ngx_close_socket_n " %s failed", |
565 ls[i].addr_text.data); | 607 ls[i].addr_text.data); |
566 } | 608 } |
567 } | 609 } |
568 | 610 |
611 | |
612 /* close the unneeded open files */ | |
613 | |
569 file = old_cycle->open_files.elts; | 614 file = old_cycle->open_files.elts; |
570 for (i = 0; i < old_cycle->open_files.nelts; i++) { | 615 for (i = 0; i < old_cycle->open_files.nelts; i++) { |
571 if (file[i].fd == NGX_INVALID_FILE) { | 616 if (file[i].fd == NGX_INVALID_FILE) { |
572 continue; | 617 continue; |
573 } | 618 } |
577 ngx_close_file_n " \"%s\" failed", | 622 ngx_close_file_n " \"%s\" failed", |
578 file[i].name.data); | 623 file[i].name.data); |
579 } | 624 } |
580 } | 625 } |
581 | 626 |
582 | 627 if (old_cycle->connections == NULL) { |
583 if (!old_cycle->one_process) { | 628 /* an old cycle is an init cycle */ |
629 ngx_destroy_pool(old_cycle->pool); | |
630 return cycle; | |
631 } | |
632 | |
633 if (master) { | |
584 ngx_destroy_pool(old_cycle->pool); | 634 ngx_destroy_pool(old_cycle->pool); |
585 return cycle; | 635 return cycle; |
586 } | 636 } |
587 | 637 |
588 if (ngx_temp_pool == NULL) { | 638 if (ngx_temp_pool == NULL) { |
624 } | 674 } |
625 | 675 |
626 return cycle; | 676 return cycle; |
627 } | 677 } |
628 | 678 |
629 | 679 #endif |
630 static int ngx_open_listening_sockets(ngx_cycle_t *cycle, ngx_log_t *log) | 680 |
681 | |
682 #if 0 | |
683 | |
684 static ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle, char **envp) | |
631 { | 685 { |
632 int times, failed, reuseaddr, i; | 686 char *p, *v; |
633 ngx_err_t err; | 687 ngx_socket_t s; |
634 ngx_socket_t s; | 688 ngx_listening_t *ls; |
635 ngx_listening_t *ls; | 689 struct sockaddr_in *addr_in; |
636 | 690 |
637 reuseaddr = 1; | 691 for ( /* void */ ; *envp; envp++) { |
638 #if (NGX_SUPPRESS_WARN) | 692 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) { |
639 failed = 0; | 693 continue; |
640 #endif | 694 } |
641 | 695 |
642 /* TODO: times configurable */ | 696 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, |
643 | 697 "using inherited sockets from \"%s\"", *envp); |
644 for (times = 10; times; times--) { | 698 |
645 failed = 0; | 699 ngx_init_array(cycle->listening, cycle->pool, |
646 | 700 10, sizeof(ngx_listening_t), NGX_ERROR); |
647 /* for each listening socket */ | 701 |
648 | 702 for (p = *envp + NGINX_VAR_LEN, v = p; *p; p++) { |
649 ls = cycle->listening.elts; | 703 if (*p == ':' || *p == ';') { |
650 for (i = 0; i < cycle->listening.nelts; i++) { | 704 s = ngx_atoi(v, p - v); |
651 | 705 if (s == NGX_ERROR) { |
652 if (ls[i].fd != -1) { | 706 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, |
653 continue; | 707 "invalid socket number \"%s\" " |
654 } | 708 "in NGINX enviroment variable, " |
655 | 709 "ignoring the rest of the variable", v); |
656 if (ls[i].inherited) { | 710 break; |
657 | 711 } |
658 /* TODO: close on exit */ | 712 v = p + 1; |
659 /* TODO: nonblocking */ | 713 |
660 /* TODO: deferred accept */ | 714 if (!(ls = ngx_push_array(&cycle->listening))) { |
661 | |
662 continue; | |
663 } | |
664 | |
665 s = ngx_socket(ls[i].family, ls[i].type, ls[i].protocol, | |
666 ls[i].flags); | |
667 | |
668 if (s == -1) { | |
669 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | |
670 ngx_socket_n " %s failed", ls[i].addr_text.data); | |
671 return NGX_ERROR; | |
672 } | |
673 | |
674 #if (WIN32) | |
675 /* | |
676 * Winsock assignes a socket number divisible by 4 | |
677 * so to find a connection we divide a socket number by 4. | |
678 */ | |
679 | |
680 if (s % 4) { | |
681 ngx_log_error(NGX_LOG_EMERG, ls->log, 0, | |
682 ngx_socket_n " created socket %d", s); | |
683 return NGX_ERROR; | |
684 } | |
685 #endif | |
686 | |
687 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, | |
688 (const void *) &reuseaddr, sizeof(int)) == -1) { | |
689 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | |
690 "setsockopt(SO_REUSEADDR) %s failed", | |
691 ls[i].addr_text.data); | |
692 return NGX_ERROR; | |
693 } | |
694 | |
695 /* TODO: close on exit */ | |
696 | |
697 if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) { | |
698 if (ngx_nonblocking(s) == -1) { | |
699 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | |
700 ngx_nonblocking_n " %s failed", | |
701 ls[i].addr_text.data); | |
702 return NGX_ERROR; | 715 return NGX_ERROR; |
703 } | 716 } |
704 } | 717 |
705 | 718 ls->fd = s; |
706 #if 0 | 719 |
707 if (ls[i].nonblocking) { | 720 /* AF_INET only */ |
708 if (ngx_nonblocking(s) == -1) { | 721 |
709 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | 722 ls->sockaddr = ngx_palloc(cycle->pool, |
710 ngx_nonblocking_n " %s failed", | 723 sizeof(struct sockaddr_in)); |
711 ls[i].addr_text.data); | 724 if (ls->sockaddr == NULL) { |
712 return NGX_ERROR; | 725 return NGX_ERROR; |
713 } | 726 } |
714 } | 727 |
715 #endif | 728 ls->socklen = sizeof(struct sockaddr_in); |
716 | 729 if (getsockname(s, ls->sockaddr, &ls->socklen) == -1) { |
717 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) { | 730 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, |
718 err = ngx_socket_errno; | 731 "getsockname() of the inherited " |
719 ngx_log_error(NGX_LOG_EMERG, log, err, | 732 "socket #%d failed", s); |
720 "bind() to %s failed", ls[i].addr_text.data); | 733 ls->ignore = 1; |
721 | 734 continue; |
722 if (err != NGX_EADDRINUSE) | 735 } |
736 | |
737 addr_in = (struct sockaddr_in *) ls->sockaddr; | |
738 | |
739 if (addr_in->sin_family != AF_INET) { | |
740 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, | |
741 "the inherited socket #%d has " | |
742 "unsupported family", s); | |
743 ls->ignore = 1; | |
744 continue; | |
745 } | |
746 ls->addr_text_max_len = INET_ADDRSTRLEN; | |
747 | |
748 ls->addr_text.data = ngx_palloc(cycle->pool, | |
749 ls->addr_text_max_len); | |
750 if (ls->addr_text.data == NULL) { | |
723 return NGX_ERROR; | 751 return NGX_ERROR; |
724 | 752 } |
725 if (ngx_close_socket(s) == -1) | 753 |
726 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | 754 addr_in->sin_len = 0; |
727 ngx_close_socket_n " %s failed", | 755 |
728 ls[i].addr_text.data); | 756 ls->family = addr_in->sin_family; |
729 | 757 ls->addr_text.len = ngx_sock_ntop(ls->family, ls->sockaddr, |
730 failed = 1; | 758 ls->addr_text.data, |
731 continue; | 759 ls->addr_text_max_len); |
732 } | 760 if (ls->addr_text.len == 0) { |
733 | 761 return NGX_ERROR; |
734 if (listen(s, ls[i].backlog) == -1) { | 762 } |
735 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | 763 } |
736 "listen() to %s failed", ls[i].addr_text.data); | 764 } |
737 return NGX_ERROR; | 765 |
738 } | 766 break; |
739 | |
740 /* TODO: deferred accept */ | |
741 | |
742 ls[i].fd = s; | |
743 } | |
744 | |
745 if (!failed) | |
746 break; | |
747 | |
748 /* TODO: delay configurable */ | |
749 | |
750 ngx_log_error(NGX_LOG_NOTICE, log, 0, | |
751 "try again to bind() after 500ms"); | |
752 ngx_msleep(500); | |
753 } | |
754 | |
755 if (failed) { | |
756 ngx_log_error(NGX_LOG_EMERG, log, 0, "still can not bind()"); | |
757 return NGX_ERROR; | |
758 } | 767 } |
759 | 768 |
760 return NGX_OK; | 769 return NGX_OK; |
761 } | 770 } |
762 | 771 |
763 | 772 #endif |
764 static void ngx_clean_old_cycles(ngx_event_t *ev) | 773 |
774 | |
775 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | |
765 { | 776 { |
766 int i, n, found, live; | 777 ngx_int_t i; |
767 ngx_log_t *log; | 778 ngx_listening_t *ls; |
768 ngx_cycle_t **cycle; | 779 |
769 | 780 if (user) { |
770 log = ngx_cycle->log; | 781 if (setuid(user) == -1) { |
771 ngx_temp_pool->log = log; | 782 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
772 | 783 "setuid() failed"); |
773 ngx_log_debug(log, "clean old cycles"); | 784 /* fatal */ |
774 | 785 exit(1); |
775 live = 0; | 786 } |
776 | 787 } |
777 cycle = ngx_old_cycles.elts; | 788 |
778 for (i = 0; i < ngx_old_cycles.nelts; i++) { | 789 ngx_init_temp_number(); |
779 | 790 |
780 if (cycle[i] == NULL) { | 791 /* |
781 continue; | 792 * disable deleting previous events for the listening sockets because |
782 } | 793 * in the worker processes there are no events at all at this point |
783 | 794 */ |
784 found = 0; | 795 ls = cycle->listening.elts; |
785 | 796 for (i = 0; i < cycle->listening.nelts; i++) { |
786 for (n = 0; n < cycle[i]->connection_n; n++) { | 797 ls[i].remain = 0; |
787 if (cycle[i]->connections[n].fd != -1) { | 798 } |
788 found = 1; | 799 |
789 ngx_log_debug(log, "live fd: %d" _ n); | 800 for (i = 0; ngx_modules[i]; i++) { |
790 break; | 801 if (ngx_modules[i]->init_process) { |
791 } | 802 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { |
792 } | 803 /* fatal */ |
793 | 804 exit(1); |
794 if (found) { | 805 } |
795 live = 1; | 806 } |
796 continue; | 807 } |
797 } | 808 |
798 | 809 /* TODO: threads: start ngx_worker_thread_cycle() */ |
799 ngx_log_debug(log, "clean old cycle: %d" _ i); | 810 |
800 ngx_destroy_pool(cycle[i]->pool); | 811 for ( ;; ) { |
801 cycle[i] = NULL; | 812 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); |
802 } | 813 |
803 | 814 ngx_process_events(cycle->log); |
804 ngx_log_debug(log, "old cycles status: %d" _ live); | 815 |
805 | 816 if (ngx_terminate) { |
806 if (live) { | 817 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); |
807 ngx_log_debug(log, "TIMER"); | 818 exit(0); |
808 ngx_add_timer(ev, 30000); | 819 } |
809 | 820 |
810 } else { | 821 if (ngx_quit) { |
811 ngx_destroy_pool(ngx_temp_pool); | 822 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, |
812 ngx_temp_pool = NULL; | 823 "gracefully shutdowning"); |
813 ngx_old_cycles.nelts = 0; | 824 break; |
825 } | |
826 | |
827 if (ngx_reopen) { | |
828 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
829 ngx_reopen_files(cycle); | |
830 ngx_reopen = 0; | |
831 } | |
832 } | |
833 | |
834 ngx_close_listening_sockets(cycle); | |
835 | |
836 for ( ;; ) { | |
837 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { | |
838 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
839 exit(0); | |
840 } | |
841 | |
842 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
843 | |
844 ngx_process_events(cycle->log); | |
814 } | 845 } |
815 } | 846 } |
847 | |
848 | |
849 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) | |
850 { | |
851 char *env[2], *var, *p; | |
852 ngx_int_t i; | |
853 ngx_exec_ctx_t ctx; | |
854 ngx_listening_t *ls; | |
855 | |
856 ctx.path = argv[0]; | |
857 ctx.name = "new binary process"; | |
858 ctx.argv = argv; | |
859 | |
860 var = ngx_alloc(NGINX_VAR_LEN | |
861 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 1, | |
862 cycle->log); | |
863 | |
864 p = ngx_cpymem(var, NGINX_VAR, NGINX_VAR_LEN); | |
865 | |
866 ls = cycle->listening.elts; | |
867 for (i = 0; i < cycle->listening.nelts; i++) { | |
868 p += ngx_snprintf(p, NGX_INT32_LEN + 2, "%u;", ls[i].fd); | |
869 } | |
870 | |
871 env[0] = var; | |
872 env[1] = NULL; | |
873 ctx.envp = (char *const *) &env; | |
874 | |
875 ngx_exec(cycle, &ctx); | |
876 | |
877 ngx_free(var); | |
878 } | |
879 | |
880 | |
881 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle) | |
882 { | |
883 ngx_core_conf_t *ccf; | |
884 | |
885 /* | |
886 * ngx_core_module has a special init procedure: it is called by | |
887 * ngx_init_cycle() before the configuration file parsing to create | |
888 * ngx_core_module configuration and to set its default parameters | |
889 */ | |
890 | |
891 if (((void **)(cycle->conf_ctx))[ngx_core_module.index] != NULL) { | |
892 return NGX_OK; | |
893 } | |
894 | |
895 if (!(ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)))) { | |
896 return NGX_ERROR; | |
897 } | |
898 /* set by pcalloc() | |
899 * | |
900 * ccf->pid = NULL; | |
901 */ | |
902 ccf->daemon = -1; | |
903 ccf->single = -1; | |
904 | |
905 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf; | |
906 | |
907 return NGX_OK; | |
908 } |