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