comparison src/os/win32/ngx_process_cycle.c @ 2725:d43d73277c5c

Win32 master/workers model
author Igor Sysoev <igor@sysoev.ru>
date Mon, 20 Apr 2009 06:08:47 +0000
parents c9da3e4dc706
children ae81441e23f4
comparison
equal deleted inserted replaced
2724:9fd2f12fee0a 2725:d43d73277c5c
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <nginx.h> 10 #include <nginx.h>
11 11
12 12
13 static ngx_thread_value_t __stdcall ngx_worker_thread_cycle(void *data); 13 static void ngx_process_init(ngx_cycle_t *cycle);
14 static void ngx_process_tray(ngx_cycle_t *cycle); 14 static void ngx_console_init(ngx_cycle_t *cycle);
15 static long __stdcall ngx_window_procedure(HWND window, u_int message, 15 static int __stdcall ngx_console_handler(u_long type);
16 u_int wparam, long lparam); 16 static ngx_int_t ngx_create_events(ngx_cycle_t *cycle);
17 17 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type);
18 #if 0 18 static void ngx_reopen_worker_processes(ngx_cycle_t *cycle);
19 ngx_pid_t ngx_new_binary; 19 static void ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old);
20 20 static void ngx_terminate_worker_processes(ngx_cycle_t *cycle);
21 sig_atomic_t ngx_reap; 21 static ngx_uint_t ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h);
22 sig_atomic_t ngx_timer; 22 static void ngx_master_process_exit(ngx_cycle_t *cycle);
23 23 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn);
24 #endif 24 static void ngx_worker_process_exit(ngx_cycle_t *cycle);
25 25 static ngx_thread_value_t __stdcall ngx_worker_thread(void *data);
26 ngx_uint_t ngx_process; 26 static ngx_thread_value_t __stdcall ngx_cache_manager_thread(void *data);
27 ngx_pid_t ngx_pid; 27 static void ngx_cache_manager_process_handler(void);
28 ngx_uint_t ngx_threaded; 28
29 ngx_uint_t ngx_inherited; 29
30 30 ngx_uint_t ngx_process;
31 31 ngx_pid_t ngx_pid;
32 sig_atomic_t ngx_terminate; 32 ngx_uint_t ngx_threaded;
33 sig_atomic_t ngx_quit; 33
34 ngx_uint_t ngx_exiting; 34 ngx_uint_t ngx_inherited;
35 35 ngx_pid_t ngx_new_binary;
36 #if 0 36
37 37 sig_atomic_t ngx_terminate;
38 sig_atomic_t ngx_noaccept; 38 sig_atomic_t ngx_quit;
39 sig_atomic_t ngx_reconfigure; 39 sig_atomic_t ngx_reopen;
40 sig_atomic_t ngx_reopen; 40 sig_atomic_t ngx_reconfigure;
41 sig_atomic_t ngx_change_binary; 41 ngx_uint_t ngx_exiting;
42 42
43 #endif 43
44 44 HANDLE ngx_master_process_event;
45 45 char ngx_master_process_event_name[NGX_PROCESS_SYNC_NAME];
46 static HMENU ngx_menu; 46
47 static HANDLE ngx_stop_event;
48 static char ngx_stop_event_name[NGX_PROCESS_SYNC_NAME];
49 static HANDLE ngx_quit_event;
50 static char ngx_quit_event_name[NGX_PROCESS_SYNC_NAME];
51 static HANDLE ngx_reopen_event;
52 static char ngx_reopen_event_name[NGX_PROCESS_SYNC_NAME];
53 static HANDLE ngx_reload_event;
54 static char ngx_reload_event_name[NGX_PROCESS_SYNC_NAME];
55
56 HANDLE ngx_cache_manager_mutex;
57 char ngx_cache_manager_mutex_name[NGX_PROCESS_SYNC_NAME];
58 HANDLE ngx_cache_manager_event;
47 59
48 60
49 void 61 void
50 ngx_master_process_cycle(ngx_cycle_t *cycle) 62 ngx_master_process_cycle(ngx_cycle_t *cycle)
51 { 63 {
52 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "master mode is not supported"); 64 u_long nev, ev, timeout;
53 65 ngx_err_t err;
54 exit(2); 66 ngx_int_t n;
55 } 67 ngx_msec_t timer;
56 68 ngx_uint_t live;
57 69 HANDLE events[MAXIMUM_WAIT_OBJECTS];
58 void 70
59 ngx_single_process_cycle(ngx_cycle_t *cycle) 71 ngx_process_init(cycle);
60 { 72
61 ngx_int_t i; 73 ngx_sprintf((u_char *) ngx_master_process_event_name,
74 "ngx_master_%s%Z", ngx_unique);
75
76 if (ngx_process == NGX_PROCESS_WORKER) {
77 ngx_worker_process_cycle(cycle, ngx_master_process_event_name);
78 return;
79 }
80
81 ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "master started");
82
83 ngx_console_init(cycle);
84
85 SetEnvironmentVariable("ngx_unique", ngx_unique);
86
87 ngx_master_process_event = CreateEvent(NULL, 1, 0,
88 ngx_master_process_event_name);
89 if (ngx_master_process_event == NULL) {
90 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
91 "CreateEvent(\"%s\") failed",
92 ngx_master_process_event_name);
93 exit(2);
94 }
95
96 if (ngx_create_events(cycle) != NGX_OK) {
97 exit(2);
98 }
99
100 ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
101 "ngx_cache_manager_mutex_%s%Z", ngx_unique);
102
103 ngx_cache_manager_mutex = CreateMutex(NULL, 0,
104 ngx_cache_manager_mutex_name);
105 if (ngx_cache_manager_mutex == NULL) {
106 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
107 "CreateMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
108 exit(2);
109 }
110
111
112 events[0] = ngx_stop_event;
113 events[1] = ngx_quit_event;
114 events[2] = ngx_reopen_event;
115 events[3] = ngx_reload_event;
116
117 ngx_close_listening_sockets(cycle);
118
119 ngx_start_worker_processes(cycle, NGX_PROCESS_RESPAWN);
120
121 timer = 0;
122 timeout = INFINITE;
123
124 for ( ;; ) {
125
126 nev = 4;
127 for (n = 0; n < ngx_last_process; n++) {
128 if (ngx_processes[n].handle) {
129 events[nev++] = ngx_processes[n].handle;
130 }
131 }
132
133 if (timer) {
134 timeout = timer > ngx_current_msec ? timer - ngx_current_msec : 0;
135 }
136
137 ev = WaitForMultipleObjects(nev, events, 0, timeout);
138
139 err = ngx_errno;
140 ngx_time_update(0, 0);
141
142 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
143 "master WaitForMultipleObjects: %ul", ev);
144
145 if (ev == WAIT_OBJECT_0) {
146 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
147
148 if (ResetEvent(ngx_stop_event) == 0) {
149 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
150 "ResetEvent(\"%s\") failed", ngx_stop_event_name);
151 }
152
153 if (timer == 0) {
154 timer = ngx_current_msec + 5000;
155 }
156
157 ngx_terminate = 1;
158 ngx_quit_worker_processes(cycle, 0);
159
160 continue;
161 }
162
163 if (ev == WAIT_OBJECT_0 + 1) {
164 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "shutting down");
165
166 if (ResetEvent(ngx_quit_event) == 0) {
167 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
168 "ResetEvent(\"%s\") failed", ngx_quit_event_name);
169 }
170
171 ngx_quit = 1;
172 ngx_quit_worker_processes(cycle, 0);
173
174 continue;
175 }
176
177 if (ev == WAIT_OBJECT_0 + 2) {
178 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
179
180 if (ResetEvent(ngx_reopen_event) == 0) {
181 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
182 "ResetEvent(\"%s\") failed",
183 ngx_reopen_event_name);
184 }
185
186 ngx_reopen_files(cycle, -1);
187 ngx_reopen_worker_processes(cycle);
188
189 continue;
190 }
191
192 if (ev == WAIT_OBJECT_0 + 3) {
193 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
194
195 if (ResetEvent(ngx_reload_event) == 0) {
196 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
197 "ResetEvent(\"%s\") failed",
198 ngx_reload_event_name);
199 }
200
201 ngx_start_worker_processes(cycle, NGX_PROCESS_JUST_RESPAWN);
202 ngx_quit_worker_processes(cycle, 1);
203
204 continue;
205 }
206
207 if (ev > WAIT_OBJECT_0 + 3 && ev < WAIT_OBJECT_0 + nev) {
208
209 ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "reap worker");
210
211 live = ngx_reap_worker(cycle, events[ev]);
212
213 if (!live && (ngx_terminate || ngx_quit)) {
214 ngx_master_process_exit(cycle);
215 }
216
217 continue;
218 }
219
220 if (ev == WAIT_TIMEOUT) {
221 ngx_terminate_worker_processes(cycle);
222
223 ngx_master_process_exit(cycle);
224 }
225
226 if (ev == WAIT_FAILED) {
227 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
228 "WaitForMultipleObjects() failed");
229
230 continue;
231 }
232
233 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
234 "WaitForMultipleObjects() returned unexpected value %ul", ev);
235 }
236 }
237
238
239 static void
240 ngx_process_init(ngx_cycle_t *cycle)
241 {
62 ngx_err_t err; 242 ngx_err_t err;
63 ngx_tid_t tid;
64 ngx_core_conf_t *ccf; 243 ngx_core_conf_t *ccf;
65
66 ngx_init_temp_number();
67
68 for (i = 0; ngx_modules[i]; i++) {
69 if (ngx_modules[i]->init_process) {
70 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
71 /* fatal */
72 exit(2);
73 }
74 }
75 }
76 244
77 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 245 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
78 246
79 if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle) 247 if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
80 != NGX_OK) 248 != NGX_OK)
88 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, 256 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
89 ngx_thread_key_create_n " failed"); 257 ngx_thread_key_create_n " failed");
90 /* fatal */ 258 /* fatal */
91 exit(2); 259 exit(2);
92 } 260 }
93 261 }
94 if (ngx_create_thread(&tid, ngx_worker_thread_cycle, NULL, cycle->log) 262
95 != 0) 263
96 { 264 static void
265 ngx_console_init(ngx_cycle_t *cycle)
266 {
267 ngx_core_conf_t *ccf;
268
269 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
270
271 if (ccf->daemon) {
272 if (FreeConsole() == 0) {
273 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
274 "FreeConsole() failed");
275 }
276
277 return;
278 }
279
280 if (SetConsoleCtrlHandler(ngx_console_handler, 1) == 0) {
281 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
282 "SetConsoleCtrlHandler() failed");
283 }
284 }
285
286
287 static int __stdcall
288 ngx_console_handler(u_long type)
289 {
290 char *msg;
291
292 switch (type) {
293
294 case CTRL_C_EVENT:
295 msg = "Ctrl-C pressed, exiting";
296 break;
297
298 case CTRL_BREAK_EVENT:
299 msg = "Ctrl-Break pressed, exiting";
300 break;
301
302 case CTRL_CLOSE_EVENT:
303 msg = "console closing, exiting";
304 break;
305
306 case CTRL_LOGOFF_EVENT:
307 msg = "user logs off, exiting";
308 break;
309
310 default:
311 return 0;
312 }
313
314 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, msg);
315
316 if (ngx_stop_event == NULL) {
317 return 1;
318 }
319
320 if (SetEvent(ngx_stop_event) == 0) {
321 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
322 "SetEvent(\"%s\") failed", ngx_stop_event_name);
323 }
324
325 return 1;
326 }
327
328
329 static ngx_int_t
330 ngx_create_events(ngx_cycle_t *cycle)
331 {
332 ngx_sprintf((u_char *) ngx_stop_event_name, "ngx_stop_%s%Z", ngx_unique);
333
334 ngx_stop_event = CreateEvent(NULL, 1, 0, ngx_stop_event_name);
335 if (ngx_stop_event == NULL) {
336 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
337 "CreateEvent(\"%s\") failed", ngx_stop_event_name);
338 return NGX_ERROR;
339 }
340
341
342 ngx_sprintf((u_char *) ngx_quit_event_name, "ngx_quit_%s%Z", ngx_unique);
343
344 ngx_quit_event = CreateEvent(NULL, 1, 0, ngx_quit_event_name);
345 if (ngx_quit_event == NULL) {
346 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
347 "CreateEvent(\"%s\") failed", ngx_quit_event_name);
348 return NGX_ERROR;
349 }
350
351
352 ngx_sprintf((u_char *) ngx_reopen_event_name,
353 "ngx_reopen_%s%Z", ngx_unique);
354
355 ngx_reopen_event = CreateEvent(NULL, 1, 0, ngx_reopen_event_name);
356 if (ngx_reopen_event == NULL) {
357 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
358 "CreateEvent(\"%s\") failed", ngx_reopen_event_name);
359 return NGX_ERROR;
360 }
361
362
363 ngx_sprintf((u_char *) ngx_reload_event_name,
364 "ngx_reload_%s%Z", ngx_unique);
365
366 ngx_reload_event = CreateEvent(NULL, 1, 0, ngx_reload_event_name);
367 if (ngx_reload_event == NULL) {
368 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
369 "CreateEvent(\"%s\") failed", ngx_reload_event_name);
370 return NGX_ERROR;
371 }
372
373 return NGX_OK;
374 }
375
376
377 static void
378 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type)
379 {
380 ngx_int_t n;
381 ngx_core_conf_t *ccf;
382
383 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
384
385 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
386
387 for (n = 0; n < ccf->worker_processes; n++) {
388 if (ngx_spawn_process(cycle, "worker", type) == NGX_INVALID_PID) {
389 return;
390 }
391 }
392 }
393
394
395 static void
396 ngx_reopen_worker_processes(ngx_cycle_t *cycle)
397 {
398 ngx_int_t n;
399
400 for (n = 0; n < ngx_last_process; n++) {
401
402 if (ngx_processes[n].handle == NULL) {
403 continue;
404 }
405
406 if (SetEvent(ngx_processes[n].reopen) == 0) {
407 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
408 "SetEvent(\"%s\") failed",
409 ngx_processes[n].reopen_event);
410 }
411 }
412 }
413
414
415 static void
416 ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old)
417 {
418 ngx_int_t n;
419
420 for (n = 0; n < ngx_last_process; n++) {
421
422 ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
423 "process: %d %P %p e:%d t:%d r:%d j:%d",
424 n,
425 ngx_processes[n].pid,
426 ngx_processes[n].handle,
427 ngx_processes[n].exiting,
428 ngx_processes[n].just_respawn);
429
430 if (old && ngx_processes[n].just_respawn) {
431 ngx_processes[n].just_respawn = 0;
432 continue;
433 }
434
435 if (ngx_processes[n].handle == NULL) {
436 continue;
437 }
438
439 if (SetEvent(ngx_processes[n].quit) == 0) {
440 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
441 "SetEvent(\"%s\") failed",
442 ngx_processes[n].quit_event);
443 }
444
445 ngx_processes[n].exiting = 1;
446 }
447 }
448
449
450 static void
451 ngx_terminate_worker_processes(ngx_cycle_t *cycle)
452 {
453 ngx_int_t n;
454
455 for (n = 0; n < ngx_last_process; n++) {
456
457 if (ngx_processes[n].handle == NULL) {
458 continue;
459 }
460
461 if (TerminateProcess(ngx_processes[n].handle, 0) == 0) {
462 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
463 "TerminateProcess(\"%p\") failed",
464 ngx_processes[n].handle);
465 }
466
467 ngx_processes[n].exiting = 1;
468
469 ngx_close_handle(ngx_processes[n].reopen);
470 ngx_close_handle(ngx_processes[n].quit);
471 ngx_close_handle(ngx_processes[n].term);
472 ngx_close_handle(ngx_processes[n].handle);
473 }
474 }
475
476
477 static ngx_uint_t
478 ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h)
479 {
480 u_long code;
481 ngx_int_t n;
482
483 for (n = 0; n < ngx_last_process; n++) {
484
485 if (ngx_processes[n].handle != h) {
486 continue;
487 }
488
489 if (GetExitCodeProcess(h, &code) == 0) {
490 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
491 "GetExitCodeProcess(%P) failed",
492 ngx_processes[n].pid);
493 }
494
495 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
496 "%s process %P exited with code %Xul",
497 ngx_processes[n].name, ngx_processes[n].pid, code);
498
499 ngx_close_handle(ngx_processes[n].reopen);
500 ngx_close_handle(ngx_processes[n].quit);
501 ngx_close_handle(ngx_processes[n].term);
502 ngx_close_handle(h);
503
504 ngx_processes[n].handle = NULL;
505 ngx_processes[n].term = NULL;
506 ngx_processes[n].quit = NULL;
507 ngx_processes[n].reopen = NULL;
508
509 if (!ngx_processes[n].exiting && !ngx_terminate && !ngx_quit) {
510
511 if (ngx_spawn_process(cycle, ngx_processes[n].name, n)
512 == NGX_INVALID_PID)
513 {
514 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
515 "can not respawn %s", ngx_processes[n].name);
516
517 if (n == ngx_last_process - 1) {
518 ngx_last_process--;
519 }
520 }
521 }
522
523 goto found;
524 }
525
526 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unknown process handle %p", h);
527
528 found:
529
530 for (n = 0; n < ngx_last_process; n++) {
531
532 ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
533 "process: %d %P %p e:%d t:%d r:%d j:%d",
534 n,
535 ngx_processes[n].pid,
536 ngx_processes[n].handle,
537 ngx_processes[n].exiting,
538 ngx_processes[n].just_respawn);
539
540 if (ngx_processes[n].handle) {
541 return 1;
542 }
543 }
544
545 return 0;
546 }
547
548
549 static void
550 ngx_master_process_exit(ngx_cycle_t *cycle)
551 {
552 ngx_uint_t i;
553
554 ngx_delete_pidfile(cycle);
555
556 ngx_close_handle(ngx_cache_manager_mutex);
557 ngx_close_handle(ngx_stop_event);
558 ngx_close_handle(ngx_quit_event);
559 ngx_close_handle(ngx_reopen_event);
560 ngx_close_handle(ngx_reload_event);
561 ngx_close_handle(ngx_master_process_event);
562
563 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
564
565 for (i = 0; ngx_modules[i]; i++) {
566 if (ngx_modules[i]->exit_master) {
567 ngx_modules[i]->exit_master(cycle);
568 }
569 }
570
571 ngx_destroy_pool(cycle->pool);
572
573 exit(0);
574 }
575
576
577 static void
578 ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn)
579 {
580 char wtevn[NGX_PROCESS_SYNC_NAME];
581 char wqevn[NGX_PROCESS_SYNC_NAME];
582 char wroevn[NGX_PROCESS_SYNC_NAME];
583 HANDLE mev, events[3];
584 u_long nev, ev;
585 ngx_err_t err;
586 ngx_tid_t wtid, cmtid;
587 ngx_log_t *log;
588
589 log = cycle->log;
590
591 ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "worker started");
592
593 ngx_sprintf((u_char *) wtevn, "ngx_worker_term_%ul%Z", ngx_pid);
594 events[0] = CreateEvent(NULL, 1, 0, wtevn);
595 if (events[0] == NULL) {
596 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
597 "CreateEvent(\"%s\") failed", wtevn);
598 goto failed;
599 }
600
601 ngx_sprintf((u_char *) wqevn, "ngx_worker_quit_%ul%Z", ngx_pid);
602 events[1] = CreateEvent(NULL, 1, 0, wqevn);
603 if (events[1] == NULL) {
604 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
605 "CreateEvent(\"%s\") failed", wqevn);
606 goto failed;
607 }
608
609 ngx_sprintf((u_char *) wroevn, "ngx_worker_reopen_%ul%Z", ngx_pid);
610 events[2] = CreateEvent(NULL, 1, 0, wroevn);
611 if (events[2] == NULL) {
612 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
613 "CreateEvent(\"%s\") failed", wroevn);
614 goto failed;
615 }
616
617 mev = OpenEvent(EVENT_MODIFY_STATE, 0, mevn);
618 if (mev == NULL) {
619 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
620 "OpenEvent(\"%s\") failed", mevn);
621 goto failed;
622 }
623
624 if (SetEvent(mev) == 0) {
625 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
626 "SetEvent(\"%s\") failed", mevn);
627 goto failed;
628 }
629
630
631 ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
632 "ngx_cache_manager_mutex_%s%Z", ngx_unique);
633
634 ngx_cache_manager_mutex = OpenMutex(SYNCHRONIZE, 0,
635 ngx_cache_manager_mutex_name);
636 if (ngx_cache_manager_mutex == NULL) {
637 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
638 "OpenMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
639 goto failed;
640 }
641
642 ngx_cache_manager_event = CreateEvent(NULL, 1, 0, NULL);
643 if (ngx_cache_manager_event == NULL) {
644 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
645 "CreateEvent(\"ngx_cache_manager_event\") failed");
646 goto failed;
647 }
648
649
650 if (ngx_create_thread(&wtid, ngx_worker_thread, NULL, log) != 0) {
651 goto failed;
652 }
653
654 if (ngx_create_thread(&cmtid, ngx_cache_manager_thread, NULL, log) != 0) {
655 goto failed;
656 }
657
658 for ( ;; ) {
659 ev = WaitForMultipleObjects(3, events, 0, INFINITE);
660
661 err = ngx_errno;
662 ngx_time_update(0, 0);
663
664 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
665 "worker WaitForMultipleObjects: %ul", ev);
666
667 if (ev == WAIT_OBJECT_0) {
668 ngx_terminate = 1;
669 ngx_log_error(NGX_LOG_NOTICE, log, 0, "exiting");
670
671 if (ResetEvent(events[0]) == 0) {
672 ngx_log_error(NGX_LOG_ALERT, log, 0,
673 "ResetEvent(\"%s\") failed", wtevn);
674 }
675
676 break;
677 }
678
679 if (ev == WAIT_OBJECT_0 + 1) {
680 ngx_quit = 1;
681 ngx_log_error(NGX_LOG_NOTICE, log, 0, "gracefully shutting down");
682 break;
683 }
684
685 if (ev == WAIT_OBJECT_0 + 2) {
686 ngx_reopen = 1;
687 ngx_log_error(NGX_LOG_NOTICE, log, 0, "reopening logs");
688
689 if (ResetEvent(events[2]) == 0) {
690 ngx_log_error(NGX_LOG_ALERT, log, 0,
691 "ResetEvent(\"%s\") failed", wroevn);
692 }
693
694 continue;
695 }
696
697 if (ev == WAIT_FAILED) {
698 ngx_log_error(NGX_LOG_ALERT, log, err,
699 "WaitForMultipleObjects() failed");
700
701 goto failed;
702 }
703 }
704
705 /* wait threads */
706
707 if (SetEvent(ngx_cache_manager_event) == 0) {
708 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
709 "SetEvent(\"ngx_cache_manager_event\") failed");
710 }
711
712 events[1] = wtid;
713 events[2] = cmtid;
714
715 nev = 3;
716
717 for ( ;; ) {
718 ev = WaitForMultipleObjects(nev, events, 0, INFINITE);
719
720 err = ngx_errno;
721 ngx_time_update(0, 0);
722
723 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
724 "worker exit WaitForMultipleObjects: %ul", ev);
725
726 if (ev == WAIT_OBJECT_0) {
727 break;
728 }
729
730 if (ev == WAIT_OBJECT_0 + 1) {
731 if (nev == 2) {
732 break;
733 }
734
735 events[1] = events[2];
736 nev = 2;
737 continue;
738 }
739
740 if (ev == WAIT_OBJECT_0 + 2) {
741 nev = 2;
742 continue;
743 }
744
745 if (ev == WAIT_FAILED) {
746 ngx_log_error(NGX_LOG_ALERT, log, err,
747 "WaitForMultipleObjects() failed");
748 break;
749 }
750 }
751
752 ngx_close_handle(ngx_cache_manager_event);
753 ngx_close_handle(events[0]);
754 ngx_close_handle(events[1]);
755 ngx_close_handle(events[2]);
756 ngx_close_handle(mev);
757
758 ngx_worker_process_exit(cycle);
759
760 failed:
761
762 exit(2);
763 }
764
765
766 static ngx_thread_value_t __stdcall
767 ngx_worker_thread(void *data)
768 {
769 ngx_int_t n;
770 ngx_uint_t i;
771 ngx_cycle_t *cycle;
772 ngx_connection_t *c;
773
774 cycle = (ngx_cycle_t *) ngx_cycle;
775
776 ngx_init_temp_number();
777
778 for (n = 0; ngx_modules[n]; n++) {
779 if (ngx_modules[n]->init_process) {
780 if (ngx_modules[n]->init_process(cycle) == NGX_ERROR) {
781 /* fatal */
782 exit(2);
783 }
784 }
785 }
786
787 while (!ngx_quit) {
788
789 if (ngx_exiting) {
790
791 c = cycle->connections;
792
793 for (i = 0; i < cycle->connection_n; i++) {
794
795 /* THREAD: lock */
796
797 if (c[i].fd != -1 && c[i].idle) {
798 c[i].close = 1;
799 c[i].read->handler(c[i].read);
800 }
801 }
802
803 if (ngx_event_timer_rbtree.root
804 == ngx_event_timer_rbtree.sentinel)
805 {
806 break;
807 }
808 }
809
810 ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "worker cycle");
811
812 ngx_process_events_and_timers(cycle);
813
814 if (ngx_terminate) {
815 return 0;
816 }
817
818 if (ngx_quit) {
819 ngx_quit = 0;
820
821 if (!ngx_exiting) {
822 ngx_close_listening_sockets(cycle);
823 ngx_exiting = 1;
824 }
825 }
826
827 if (ngx_reopen) {
828 ngx_reopen = 0;
829 ngx_reopen_files(cycle, -1);
830 }
831 }
832
833 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
834
835 return 0;
836 }
837
838
839 static void
840 ngx_worker_process_exit(ngx_cycle_t *cycle)
841 {
842 ngx_uint_t i;
843 ngx_connection_t *c;
844
845 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
846
847 for (i = 0; ngx_modules[i]; i++) {
848 if (ngx_modules[i]->exit_process) {
849 ngx_modules[i]->exit_process(cycle);
850 }
851 }
852
853 if (ngx_exiting) {
854 c = cycle->connections;
855 for (i = 0; i < cycle->connection_n; i++) {
856 if (c[i].fd != -1
857 && c[i].read
858 && !c[i].read->accept
859 && !c[i].read->channel
860 && !c[i].read->resolver)
861 {
862 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
863 "open socket #%d left in connection %ui",
864 c[i].fd, i);
865 }
866 }
867 }
868
869 ngx_destroy_pool(cycle->pool);
870
871 exit(0);
872 }
873
874
875 static ngx_thread_value_t __stdcall
876 ngx_cache_manager_thread(void *data)
877 {
878 u_long ev;
879 HANDLE events[2];
880 ngx_err_t err;
881 ngx_cycle_t *cycle;
882
883 cycle = (ngx_cycle_t *) ngx_cycle;
884
885 events[0] = ngx_cache_manager_event;
886 events[1] = ngx_cache_manager_mutex;
887
888 for ( ;; ) {
889 ev = WaitForMultipleObjects(2, events, 0, INFINITE);
890
891 err = ngx_errno;
892 ngx_time_update(0, 0);
893
894 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
895 "cache manager WaitForMultipleObjects: %ul", ev);
896
897 if (ev == WAIT_FAILED) {
898 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
899 "WaitForMultipleObjects() failed");
900 }
901
902 /*
903 * ev == WAIT_OBJECT_0
904 * ev == WAIT_OBJECT_0 + 1
905 * ev == WAIT_ABANDONED_0 + 1
906 */
907
908 if (ngx_terminate || ngx_quit) {
909 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
910 return 0;
911 }
912
913 break;
914 }
915
916 for ( ;; ) {
917
918 if (ngx_terminate || ngx_quit) {
919 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
920 break;
921 }
922
923 ngx_cache_manager_process_handler();
924 }
925
926 if (ReleaseMutex(ngx_cache_manager_mutex) == 0) {
927 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
928 "ReleaseMutex() failed");
929 }
930
931 return 0;
932 }
933
934
935 static void
936 ngx_cache_manager_process_handler(void)
937 {
938 u_long ev;
939 time_t next, n;
940 ngx_uint_t i;
941 ngx_path_t **path;
942
943 next = 60 * 60;
944
945 path = ngx_cycle->pathes.elts;
946 for (i = 0; i < ngx_cycle->pathes.nelts; i++) {
947
948 if (path[i]->manager) {
949 n = path[i]->manager(path[i]->data);
950
951 next = (n <= next) ? n : next;
952
953 ngx_time_update(0, 0);
954 }
955 }
956
957 if (next == 0) {
958 next = 1;
959 }
960
961 ev = WaitForSingleObject(ngx_cache_manager_event, (u_long) next * 1000);
962
963 if (ev != WAIT_TIMEOUT) {
964
965 ngx_time_update(0, 0);
966
967 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
968 "cache manager WaitForSingleObject: %ul", ev);
969 }
970 }
971
972
973 void
974 ngx_single_process_cycle(ngx_cycle_t *cycle)
975 {
976 ngx_int_t i;
977 ngx_tid_t tid;
978
979 ngx_init_temp_number();
980
981 for (i = 0; ngx_modules[i]; i++) {
982 if (ngx_modules[i]->init_process) {
983 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
984 /* fatal */
985 exit(2);
986 }
987 }
988 }
989
990 ngx_process_init(cycle);
991
992 ngx_console_init(cycle);
993
994 if (ngx_create_events(cycle) != NGX_OK) {
995 exit(2);
996 }
997
998 if (ngx_create_thread(&tid, ngx_worker_thread, NULL, cycle->log) != 0) {
97 /* fatal */ 999 /* fatal */
98 exit(2); 1000 exit(2);
99 } 1001 }
100 1002
101 ngx_process_tray(cycle); 1003 /* STUB */
102 } 1004 WaitForSingleObject(ngx_stop_event, INFINITE);
103 1005 }
104 1006
105 static ngx_thread_value_t __stdcall 1007
106 ngx_worker_thread_cycle(void *data) 1008 ngx_int_t
107 { 1009 ngx_signal_process(ngx_cycle_t *cycle, char *sig)
108 ngx_cycle_t *cycle; 1010 {
109 1011 size_t n;
110 cycle = (ngx_cycle_t *) ngx_cycle; 1012 HANDLE ev;
111 1013 ngx_int_t rc, pid;
112 while (!ngx_quit) { 1014 ngx_file_t file;
113 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); 1015 ngx_core_conf_t *ccf;
114 1016 u_char buf[NGX_INT64_LEN + 2];
115 ngx_process_events_and_timers(cycle); 1017 char evn[NGX_PROCESS_SYNC_NAME];
116 } 1018
117 1019 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");
118 return 0; 1020
119 } 1021 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
120 1022
121 1023 file.name = ccf->pid;
122 static void 1024 file.log = cycle->log;
123 ngx_process_tray(ngx_cycle_t *cycle) 1025
124 { 1026 file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
125 int rc; 1027 NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);
126 MSG message; 1028
127 HWND window; 1029 if (file.fd == NGX_INVALID_FILE) {
128 HMENU menu; 1030 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
129 HICON icon, tray; 1031 ngx_open_file_n " \"%s\" failed", file.name.data);
130 WNDCLASS wc; 1032 return 1;
131 HINSTANCE instance; 1033 }
132 1034
133 instance = GetModuleHandle(NULL); 1035 rc = 1;
134 1036
135 icon = LoadIcon(instance, "nginx"); 1037 n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);
136 if (icon == NULL) { 1038
137 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 1039 if (n == NGX_ERROR) {
138 "LoadIcon(\"nginx\") failed"); 1040 goto failed;
139 /* fatal */ 1041 }
140 exit(2); 1042
141 } 1043 while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }
142 1044
143 tray = LoadIcon(instance, "tray"); 1045 pid = ngx_atoi(buf, ++n);
144 if (icon == NULL) { 1046
145 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 1047 if (pid == NGX_ERROR) {
146 "LoadIcon(\"tray\") failed"); 1048 ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
147 /* fatal */ 1049 "invalid PID number \"%*s\" in \"%s\"",
148 exit(2); 1050 n, buf, file.name.data);
149 } 1051 goto failed;
150 1052 }
151 menu = LoadMenu(instance, "nginx"); 1053
152 if (menu == NULL) { 1054 ngx_sprintf((u_char *) evn, "ngx_%s_%ul%Z", sig, pid);
153 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 1055
154 "LoadMenu() failed"); 1056 ev = OpenEvent(EVENT_MODIFY_STATE, 0, evn);
155 /* fatal */ 1057 if (ev == NULL) {
156 exit(2); 1058 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
157 } 1059 "OpenEvent(\"%s\") failed", evn);
158 1060 goto failed;
159 ngx_menu = GetSubMenu(menu, 0); 1061 }
160 if (ngx_menu == NULL) { 1062
161 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 1063 if (SetEvent(ev) == 0) {
162 "GetSubMenu() failed"); 1064 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
163 /* fatal */ 1065 "SetEvent(\"%s\") failed", evn);
164 exit(2); 1066 } else {
165 } 1067 rc = 0;
166 1068 }
167 1069
168 wc.style = CS_HREDRAW|CS_VREDRAW; 1070 ngx_close_handle(ev);
169 wc.lpfnWndProc = ngx_window_procedure; 1071
170 wc.cbClsExtra = 0; 1072 failed:
171 wc.cbWndExtra = 0; 1073
172 wc.hInstance = instance; 1074 if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
173 wc.hIcon = icon; 1075 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
174 wc.hCursor = NULL; 1076 ngx_close_file_n " \"%s\" failed", file.name.data);
175 wc.hbrBackground = NULL; 1077 }
176 wc.lpszMenuName = NULL; 1078
177 wc.lpszClassName = "nginx"; 1079 return rc;
178 1080 }
179 if (RegisterClass(&wc) == 0) { 1081
180 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 1082
181 "RegisterClass() failed"); 1083 void
182 /* fatal */ 1084 ngx_close_handle(HANDLE h)
183 exit(2); 1085 {
184 } 1086 if (CloseHandle(h) == 0) {
185 1087 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
186 window = CreateWindow("nginx", "nginx", WS_OVERLAPPEDWINDOW, 1088 "CloseHandle(%p) failed", h);
187 CW_USEDEFAULT, CW_USEDEFAULT, 1089 }
188 CW_USEDEFAULT, CW_USEDEFAULT, 1090 }
189 NULL, NULL, instance, NULL);
190
191 if (window == NULL) {
192 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
193 "CreateWindow() failed");
194 /* fatal */
195 exit(2);
196 }
197
198
199 if (ngx_system_tray_icon(window, NIM_ADD, tray, (u_char *) " nginx")
200 != NGX_OK)
201 {
202 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
203 "Shell_NotifyIcon(NIM_ADD) failed");
204 /* fatal */
205 exit(2);
206 }
207
208 for ( ;; ) {
209 rc = GetMessage(&message, NULL, 0, 0);
210
211 if (rc == -1) {
212 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
213 "GetMessage() failed");
214 continue;
215 }
216
217 if (rc == 0) {
218 exit(0);
219 }
220
221 TranslateMessage(&message);
222 DispatchMessage(&message);
223 }
224 }
225
226
227 static long __stdcall
228 ngx_window_procedure(HWND window, u_int message, u_int wparam, long lparam)
229 {
230 POINT mouse;
231
232 switch (message) {
233
234 case NGX_WM_TRAY:
235 if (lparam == WM_RBUTTONDOWN) {
236 if (GetCursorPos(&mouse) == 0) {
237 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
238 "GetCursorPos() failed");
239 return 0;
240 }
241
242 if (SetForegroundWindow(window) == 0) {
243 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
244 "SetForegroundWindow() failed");
245 return 0;
246 }
247
248 if (TrackPopupMenu(ngx_menu, TPM_RIGHTBUTTON,
249 mouse.x, mouse.y, 0, window, NULL)
250 == 0)
251 {
252 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
253 "TrackPopupMenu() failed");
254 return 0;
255 }
256 }
257
258 return 0;
259
260 case WM_COMMAND:
261 if (wparam == NGX_WM_ABOUT) {
262 ngx_message_box("nginx", MB_OK, 0,
263 NGINX_VER CRLF "(C) 2002-2009 Igor Sysoev");
264 return 0;
265 }
266
267 if (wparam == NGX_WM_EXIT) {
268 if (ngx_system_tray_icon(window, NIM_DELETE, NULL, NULL)
269 != NGX_OK)
270 {
271 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
272 "Shell_NotifyIcon(NIM_DELETE) failed");
273 }
274 }
275
276 PostQuitMessage(0);
277
278 return 0;
279
280 default:
281 return DefWindowProc(window, message, wparam, lparam);
282 }
283 }