comparison src/os/unix/ngx_process_cycle.c @ 502:89dc5654117c NGINX_0_7_63

nginx 0.7.63 *) Security: now "/../" are disabled in "Destination" request header line. *) Change: minimum supported OpenSSL version is 0.9.7. *) Change: the "ask" parameter of the "ssl_verify_client" directive was changed to the "optional" parameter and now it checks a client certificate if it was offered. Thanks to Brice Figureau. *) Feature: now the "-V" switch shows TLS SNI support. *) Feature: the $ssl_client_verify variable. Thanks to Brice Figureau. *) Feature: the "ssl_crl" directive. Thanks to Brice Figureau. *) Bugfix: the $ssl_client_cert variable usage corrupted memory; the bug had appeared in 0.7.7. Thanks to Sergey Zhuravlev. *) Feature: now the start cache loader runs in a separate process; this should improve large caches handling. *) Feature: now temporary files and permanent storage area may reside at different file systems. *) Bugfix: nginx counted incorrectly disk cache size. *) Change: now directive "gzip_disable msie6" does not disable gzipping for MSIE 6.0 SV1. *) Bugfix: nginx always added "Vary: Accept-Encoding" response header line, if both "gzip_static" and "gzip_vary" were on. *) Feature: the "proxy" parameter of the "geo" directive. *) Feature: the ngx_http_geoip_module. *) Feature: the "limit_rate_after" directive. Thanks to Ivan Debnar. *) Feature: the "limit_req_log_level" and "limit_conn_log_level" directives. *) Bugfix: now "limit_req" directive conforms to the leaky bucket algorithm. Thanks to Maxim Dounin. *) Bugfix: in ngx_http_limit_req_module. Thanks to Maxim Dounin. *) Bugfix: now nginx allows underscores in a request method. *) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate", "X-Accel-Buffering", and "X-Accel-Charset" lines from backend response header. Thanks to Maxim Dounin. *) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend response header lines; the bug had appeared in 0.7.44. Thanks to Maxim Dounin. *) Feature: the "image_filter_transparency" directive. *) Feature: the "image_filter" directive supports variables for setting size. *) Bugfix: in PNG alpha-channel support in the ngx_http_image_filter_module. *) Bugfix: in transparency support in the ngx_http_image_filter_module. *) Feature: now several "perl_modules" directives may be used. *) Bugfix: ngx_http_perl_module responses did not work in subrequests. *) Bugfix: nginx sent '\0' in a "Location" response header line on MKCOL request. Thanks to Xie Zhenye. *) Bugfix: an "error_page" directive did not redirect a 413 error; the bug had appeared in 0.6.10. *) Bugfix: in memory allocation error handling. Thanks to Maxim Dounin and Kirill A. Korinskiy.
author Igor Sysoev <http://sysoev.ru>
date Mon, 26 Oct 2009 00:00:00 +0300
parents ed3d382670c7
children b9fdcaf2062b
comparison
equal deleted inserted replaced
501:dc87c92181c7 502:89dc5654117c
10 #include <ngx_channel.h> 10 #include <ngx_channel.h>
11 11
12 12
13 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, 13 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
14 ngx_int_t type); 14 ngx_int_t type);
15 static void ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type); 15 static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
16 ngx_uint_t respawn);
17 static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
16 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); 18 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
17 static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle); 19 static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
18 static void ngx_master_process_exit(ngx_cycle_t *cycle); 20 static void ngx_master_process_exit(ngx_cycle_t *cycle);
19 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); 21 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
20 static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority); 22 static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority);
24 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); 26 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle);
25 static ngx_thread_value_t ngx_worker_thread_cycle(void *data); 27 static ngx_thread_value_t ngx_worker_thread_cycle(void *data);
26 #endif 28 #endif
27 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data); 29 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
28 static void ngx_cache_manager_process_handler(ngx_event_t *ev); 30 static void ngx_cache_manager_process_handler(ngx_event_t *ev);
31 static void ngx_cache_loader_process_handler(ngx_event_t *ev);
29 32
30 33
31 ngx_uint_t ngx_process; 34 ngx_uint_t ngx_process;
32 ngx_pid_t ngx_pid; 35 ngx_pid_t ngx_pid;
33 ngx_uint_t ngx_threaded; 36 ngx_uint_t ngx_threaded;
58 #endif 61 #endif
59 62
60 63
61 u_long cpu_affinity; 64 u_long cpu_affinity;
62 static u_char master_process[] = "master process"; 65 static u_char master_process[] = "master process";
66
67
68 static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = {
69 ngx_cache_manager_process_handler, "cache manager process", 0
70 };
71
72 static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = {
73 ngx_cache_loader_process_handler, "cache loader process", 60000
74 };
63 75
64 76
65 static ngx_cycle_t ngx_exit_cycle; 77 static ngx_cycle_t ngx_exit_cycle;
66 static ngx_log_t ngx_exit_log; 78 static ngx_log_t ngx_exit_log;
67 static ngx_open_file_t ngx_exit_log_file; 79 static ngx_open_file_t ngx_exit_log_file;
121 133
122 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 134 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
123 135
124 ngx_start_worker_processes(cycle, ccf->worker_processes, 136 ngx_start_worker_processes(cycle, ccf->worker_processes,
125 NGX_PROCESS_RESPAWN); 137 NGX_PROCESS_RESPAWN);
126 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); 138 ngx_start_cache_manager_processes(cycle, 0);
127 139
128 ngx_new_binary = 0; 140 ngx_new_binary = 0;
129 delay = 0; 141 delay = 0;
130 live = 1; 142 live = 1;
131 143
205 ngx_reconfigure = 0; 217 ngx_reconfigure = 0;
206 218
207 if (ngx_new_binary) { 219 if (ngx_new_binary) {
208 ngx_start_worker_processes(cycle, ccf->worker_processes, 220 ngx_start_worker_processes(cycle, ccf->worker_processes,
209 NGX_PROCESS_RESPAWN); 221 NGX_PROCESS_RESPAWN);
210 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); 222 ngx_start_cache_manager_processes(cycle, 0);
211 ngx_noaccepting = 0; 223 ngx_noaccepting = 0;
212 224
213 continue; 225 continue;
214 } 226 }
215 227
224 ngx_cycle = cycle; 236 ngx_cycle = cycle;
225 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, 237 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
226 ngx_core_module); 238 ngx_core_module);
227 ngx_start_worker_processes(cycle, ccf->worker_processes, 239 ngx_start_worker_processes(cycle, ccf->worker_processes,
228 NGX_PROCESS_JUST_RESPAWN); 240 NGX_PROCESS_JUST_RESPAWN);
229 ngx_start_cache_manager_process(cycle, NGX_PROCESS_JUST_RESPAWN); 241 ngx_start_cache_manager_processes(cycle, 1);
230 live = 1; 242 live = 1;
231 ngx_signal_worker_processes(cycle, 243 ngx_signal_worker_processes(cycle,
232 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); 244 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
233 } 245 }
234 246
235 if (ngx_restart) { 247 if (ngx_restart) {
236 ngx_restart = 0; 248 ngx_restart = 0;
237 ngx_start_worker_processes(cycle, ccf->worker_processes, 249 ngx_start_worker_processes(cycle, ccf->worker_processes,
238 NGX_PROCESS_RESPAWN); 250 NGX_PROCESS_RESPAWN);
239 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); 251 ngx_start_cache_manager_processes(cycle, 0);
240 live = 1; 252 live = 1;
241 } 253 }
242 254
243 if (ngx_reopen) { 255 if (ngx_reopen) {
244 ngx_reopen = 0; 256 ngx_reopen = 0;
267 void 279 void
268 ngx_single_process_cycle(ngx_cycle_t *cycle) 280 ngx_single_process_cycle(ngx_cycle_t *cycle)
269 { 281 {
270 ngx_uint_t i; 282 ngx_uint_t i;
271 283
272 ngx_init_temp_number();
273
274 for (i = 0; ngx_modules[i]; i++) { 284 for (i = 0; ngx_modules[i]; i++) {
275 if (ngx_modules[i]->init_process) { 285 if (ngx_modules[i]->init_process) {
276 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { 286 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
277 /* fatal */ 287 /* fatal */
278 exit(2); 288 exit(2);
319 329
320 330
321 static void 331 static void
322 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) 332 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
323 { 333 {
324 ngx_int_t i, s; 334 ngx_int_t i;
325 ngx_channel_t ch; 335 ngx_channel_t ch;
326 336
327 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); 337 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
328 338
329 ch.command = NGX_CMD_OPEN_CHANNEL; 339 ch.command = NGX_CMD_OPEN_CHANNEL;
337 347
338 ch.pid = ngx_processes[ngx_process_slot].pid; 348 ch.pid = ngx_processes[ngx_process_slot].pid;
339 ch.slot = ngx_process_slot; 349 ch.slot = ngx_process_slot;
340 ch.fd = ngx_processes[ngx_process_slot].channel[0]; 350 ch.fd = ngx_processes[ngx_process_slot].channel[0];
341 351
342 for (s = 0; s < ngx_last_process; s++) { 352 ngx_pass_open_channel(cycle, &ch);
343
344 if (s == ngx_process_slot
345 || ngx_processes[s].pid == -1
346 || ngx_processes[s].channel[0] == -1)
347 {
348 continue;
349 }
350
351 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
352 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
353 ch.slot, ch.pid, ch.fd,
354 s, ngx_processes[s].pid,
355 ngx_processes[s].channel[0]);
356
357 /* TODO: NGX_AGAIN */
358
359 ngx_write_channel(ngx_processes[s].channel[0],
360 &ch, sizeof(ngx_channel_t), cycle->log);
361 }
362 } 353 }
363 } 354 }
364 355
365 356
366 static void 357 static void
367 ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type) 358 ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
368 { 359 {
369 ngx_int_t i; 360 ngx_uint_t i, manager, loader;
370 ngx_uint_t n;
371 ngx_path_t **path; 361 ngx_path_t **path;
372 ngx_channel_t ch; 362 ngx_channel_t ch;
373 363
364 manager = 0;
365 loader = 0;
366
374 path = ngx_cycle->pathes.elts; 367 path = ngx_cycle->pathes.elts;
375 for (n = 0; n < ngx_cycle->pathes.nelts; n++) { 368 for (i = 0; i < ngx_cycle->pathes.nelts; i++) {
376 if (path[n]->manager) { 369
377 goto start; 370 if (path[i]->manager) {
378 } 371 manager = 1;
379 } 372 }
380 373
381 return; 374 if (path[i]->loader) {
382 375 loader = 1;
383 start: 376 }
377 }
378
379 if (manager == 0) {
380 return;
381 }
382
383 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
384 &ngx_cache_manager_ctx, "cache manager process",
385 respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
384 386
385 ch.command = NGX_CMD_OPEN_CHANNEL; 387 ch.command = NGX_CMD_OPEN_CHANNEL;
386
387 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, NULL,
388 "cache manager process", type);
389
390 ch.pid = ngx_processes[ngx_process_slot].pid; 388 ch.pid = ngx_processes[ngx_process_slot].pid;
391 ch.slot = ngx_process_slot; 389 ch.slot = ngx_process_slot;
392 ch.fd = ngx_processes[ngx_process_slot].channel[0]; 390 ch.fd = ngx_processes[ngx_process_slot].channel[0];
391
392 ngx_pass_open_channel(cycle, &ch);
393
394 if (loader == 0) {
395 return;
396 }
397
398 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
399 &ngx_cache_loader_ctx, "cache loader process",
400 respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
401
402 ch.command = NGX_CMD_OPEN_CHANNEL;
403 ch.pid = ngx_processes[ngx_process_slot].pid;
404 ch.slot = ngx_process_slot;
405 ch.fd = ngx_processes[ngx_process_slot].channel[0];
406
407 ngx_pass_open_channel(cycle, &ch);
408 }
409
410
411 static void
412 ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
413 {
414 ngx_int_t i;
393 415
394 for (i = 0; i < ngx_last_process; i++) { 416 for (i = 0; i < ngx_last_process; i++) {
395 417
396 if (i == ngx_process_slot 418 if (i == ngx_process_slot
397 || ngx_processes[i].pid == -1 419 || ngx_processes[i].pid == -1
400 continue; 422 continue;
401 } 423 }
402 424
403 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, 425 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
404 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", 426 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
405 ch.slot, ch.pid, ch.fd, 427 ch->slot, ch->pid, ch->fd,
406 i, ngx_processes[i].pid, 428 i, ngx_processes[i].pid,
407 ngx_processes[i].channel[0]); 429 ngx_processes[i].channel[0]);
408 430
409 /* TODO: NGX_AGAIN */ 431 /* TODO: NGX_AGAIN */
410 432
411 ngx_write_channel(ngx_processes[i].channel[0], 433 ngx_write_channel(ngx_processes[i].channel[0],
412 &ch, sizeof(ngx_channel_t), cycle->log); 434 ch, sizeof(ngx_channel_t), cycle->log);
413 } 435 }
414 } 436 }
415 437
416 438
417 static void 439 static void
458 ngx_processes[i].pid, 480 ngx_processes[i].pid,
459 ngx_processes[i].exiting, 481 ngx_processes[i].exiting,
460 ngx_processes[i].exited, 482 ngx_processes[i].exited,
461 ngx_processes[i].detached, 483 ngx_processes[i].detached,
462 ngx_processes[i].respawn, 484 ngx_processes[i].respawn,
463 ngx_processes[i].just_respawn); 485 ngx_processes[i].just_spawn);
464 486
465 if (ngx_processes[i].detached || ngx_processes[i].pid == -1) { 487 if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
466 continue; 488 continue;
467 } 489 }
468 490
469 if (ngx_processes[i].just_respawn) { 491 if (ngx_processes[i].just_spawn) {
470 ngx_processes[i].just_respawn = 0; 492 ngx_processes[i].just_spawn = 0;
471 continue; 493 continue;
472 } 494 }
473 495
474 if (ngx_processes[i].exiting 496 if (ngx_processes[i].exiting
475 && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL)) 497 && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
534 ngx_processes[i].pid, 556 ngx_processes[i].pid,
535 ngx_processes[i].exiting, 557 ngx_processes[i].exiting,
536 ngx_processes[i].exited, 558 ngx_processes[i].exited,
537 ngx_processes[i].detached, 559 ngx_processes[i].detached,
538 ngx_processes[i].respawn, 560 ngx_processes[i].respawn,
539 ngx_processes[i].just_respawn); 561 ngx_processes[i].just_spawn);
540 562
541 if (ngx_processes[i].pid == -1) { 563 if (ngx_processes[i].pid == -1) {
542 continue; 564 continue;
543 } 565 }
544 566
591 ch.command = NGX_CMD_OPEN_CHANNEL; 613 ch.command = NGX_CMD_OPEN_CHANNEL;
592 ch.pid = ngx_processes[ngx_process_slot].pid; 614 ch.pid = ngx_processes[ngx_process_slot].pid;
593 ch.slot = ngx_process_slot; 615 ch.slot = ngx_process_slot;
594 ch.fd = ngx_processes[ngx_process_slot].channel[0]; 616 ch.fd = ngx_processes[ngx_process_slot].channel[0];
595 617
596 for (n = 0; n < ngx_last_process; n++) { 618 ngx_pass_open_channel(cycle, &ch);
597
598 if (n == ngx_process_slot
599 || ngx_processes[n].pid == -1
600 || ngx_processes[n].channel[0] == -1)
601 {
602 continue;
603 }
604
605 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
606 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
607 ch.slot, ch.pid, ch.fd,
608 n, ngx_processes[n].pid,
609 ngx_processes[n].channel[0]);
610
611 /* TODO: NGX_AGAIN */
612
613 ngx_write_channel(ngx_processes[n].channel[0],
614 &ch, sizeof(ngx_channel_t), cycle->log);
615 }
616 619
617 live = 1; 620 live = 1;
618 621
619 continue; 622 continue;
620 } 623 }
925 928
926 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { 929 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
927 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 930 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
928 "sigprocmask() failed"); 931 "sigprocmask() failed");
929 } 932 }
930
931 ngx_init_temp_number();
932 933
933 /* 934 /*
934 * disable deleting previous events for the listening sockets because 935 * disable deleting previous events for the listening sockets because
935 * in the worker processes there are no events at all at this point 936 * in the worker processes there are no events at all at this point
936 */ 937 */
1266 1267
1267 1268
1268 static void 1269 static void
1269 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) 1270 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
1270 { 1271 {
1272 ngx_cache_manager_ctx_t *ctx = data;
1273
1271 void *ident[4]; 1274 void *ident[4];
1272 ngx_event_t ev; 1275 ngx_event_t ev;
1273 1276
1274 cycle->connection_n = 512; 1277 cycle->connection_n = 512;
1275 1278
1276 ngx_worker_process_init(cycle, 0); 1279 ngx_worker_process_init(cycle, 0);
1277 1280
1278 ngx_close_listening_sockets(cycle); 1281 ngx_close_listening_sockets(cycle);
1279 1282
1280 ngx_memzero(&ev, sizeof(ngx_event_t)); 1283 ngx_memzero(&ev, sizeof(ngx_event_t));
1281 ev.handler = ngx_cache_manager_process_handler; 1284 ev.handler = ctx->handler;
1282 ev.data = ident; 1285 ev.data = ident;
1283 ev.log = cycle->log; 1286 ev.log = cycle->log;
1284 ident[3] = (void *) -1; 1287 ident[3] = (void *) -1;
1285 1288
1286 ngx_use_accept_mutex = 0; 1289 ngx_use_accept_mutex = 0;
1287 1290
1288 ngx_setproctitle("cache manager process"); 1291 ngx_setproctitle(ctx->name);
1289 1292
1290 ngx_add_timer(&ev, 0); 1293 ngx_add_timer(&ev, ctx->delay);
1291 1294
1292 for ( ;; ) { 1295 for ( ;; ) {
1293 1296
1294 if (ngx_terminate || ngx_quit) { 1297 if (ngx_terminate || ngx_quit) {
1295 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); 1298 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
1332 next = 1; 1335 next = 1;
1333 } 1336 }
1334 1337
1335 ngx_add_timer(ev, next * 1000); 1338 ngx_add_timer(ev, next * 1000);
1336 } 1339 }
1340
1341
1342 static void
1343 ngx_cache_loader_process_handler(ngx_event_t *ev)
1344 {
1345 ngx_uint_t i;
1346 ngx_path_t **path;
1347 ngx_cycle_t *cycle;
1348
1349 cycle = (ngx_cycle_t *) ngx_cycle;
1350
1351 path = cycle->pathes.elts;
1352 for (i = 0; i < cycle->pathes.nelts; i++) {
1353
1354 if (ngx_terminate || ngx_quit) {
1355 break;
1356 }
1357
1358 if (path[i]->loader) {
1359 path[i]->loader(path[i]->data);
1360 ngx_time_update(0, 0);
1361 }
1362 }
1363
1364 exit(0);
1365 }