Chinaunix首页 | 论坛 | 博客
  • 博客访问: 93496
  • 博文数量: 9
  • 博客积分: 330
  • 博客等级: 一等列兵
  • 技术积分: 117
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-05 18:36
文章分类

全部博文(9)

文章存档

2012年(4)

2011年(1)

2010年(4)

分类: C/C++

2012-09-14 16:04:50

nginx的进程模式

1 进程间的通信方式
    使用 UNIX域套接字 socketpair() 异步通讯机制: nginx在创建worker前将先调用 socketpair(int channel[2]) 然后将 channel[0-1]设置为异步通知方式,并注册evnet事件,父进程使用channel[0],子进程使用channel[1]实现双方的通讯.

2 都有哪些通信?
2.1 创建worker进程时
2.2 执行 nginx -s reload 时
2.3 执行 nginx -s stop 时
2.4 执行 nginx -s quit 时
2.5 执行 nginx -s reopen 时
2.6 某worker异常退出时
2.7 概要

点击(此处)折叠或打开

  1. SIGHUP NGX_CMD_QUIT|SIGQUIT
  2.     ./nginx -s reload ---------> master (ngx_reload=1) -------------------------> worker|cache_manager|cache_loader (ngx_quit=1, 处理完待读socket再退出)


  3.                       SIGTERM|SIGINT NGX_CMD_TERMINATE|SIGTERM
  4.     ./nginx -s stop -----------------> master (ngx_terminate=1,延迟退出时间) ----------------------------> worker|cache_manager|cache_loader (ngx_terminate=1,直接退出)


  5.                       SIGQUIT NGX_CMD_QUIT|SIGQUIT
  6.     ./nginx -s quit ----------> master (ngx_quit=1) ------------------------> worker|cache_manager|cache_loader (ngx_quit=1, 处理完待读socket再退出)

  7.                         SIGUSER1 NGX_CMD_REOPEN|SIGUSER1
  8.     ./nginx -s reopen -----------> master (ngx_reopen=1) -------------------------> worker|cache_manager|cache_loader (ngx_reopen=1)


3 通信的内容是什么?

点击(此处)折叠或打开

  1. src/os/unix/ngx_process_cycle.h:
  2.     #define NGX_CMD_OPEN_CHANNEL 1
  3.     #define NGX_CMD_CLOSE_CHANNEL 2
  4.     #define NGX_CMD_QUIT 3
  5.     #define NGX_CMD_TERMINATE 4
  6.     #define NGX_CMD_REOPEN 5


4 创建worker进程时 是如何通信的?
master(父进程):
    1> 在进程池 ngx_processes 中为 新worker进程 分配一个位置,如果进程池已满,也就是创建的进程数超过了最大值1024 nginx报错但不退出;
    2> 调用 socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) 创建UNIX域套接字对.并设置为异步模式且execve时关闭;
    3> 将 新worker进程 的{NGX_CMD_OPEN_CHANNEL, channel[0], 在进程池中的位置, PID} 通过 UNIX域套接字 告知已存在的子进程.

点击(此处)折叠或打开

  1. {
  2.         ngx_start_worker_processes()
  3.         {
  4.             ch.command=NGX_CMD_OPEN_CHANNEL;
  5.             for (i=0; i < n; i++) {
  6.                 //...
  7.                 ch.pid=ngx_processes[ngx_process_slot].pid;
  8.                 ch.slot=ngx_process_slot;
  9.                 ch.fd=ngx_processes[ngx_process_slot].channel[0];
  10.                 ngx_pass_open_channel(cycle, &ch);
  11.             }
  12.         }
  13. }


新worker进程:
    1> 关闭进程池中其他子进程的 channel[1];
    2> 关闭自身的 channel[0];
    3> 将自身的 channel[1] 注册event读事件: ngx_channel_handler().

点击(此处)折叠或打开

  1. {
  2.     ngx_worker_process_cycle()
  3.     {
  4.         //...
  5.         ngx_worker_process_init()
  6.         {
  7.             //...
  8.             for (n=0; n < ngx_last_process; n++) {

  9.                 if (ngx_processes[n].pid == -1) {
  10.                     continue;
  11.                 }

  12.                 if (n == ngx_process_slot) {
  13.                     continue;
  14.                 }

  15.                 if (ngx_processes[n].channel[1] == -1) {
  16.                     continue;
  17.                 }

  18.                 if (close(ngx_processes[n].channel[1]) == -1) {
  19.                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  20.                             "close() channel failed");
  21.                 }
  22.             }

  23.             if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
  24.             }
  25.             if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
  26.                         ngx_channel_handler)
  27.                     == NGX_ERROR)
  28.             {
  29.                 /* fatal */
  30.                 exit(2);
  31.             }
  32.         }
  33.     }
  34. }


    自身可以通过 进程池中其他子进程的 channel[0] 收发 其他子进程 的信息.
    自身可以通过 自身的 channel[1] 收发 master进程 的信息.
    
其他子进程:
    此时 其他子进程的 UNIX域套接字 收到 master进程的 {NGX_CMD_OPEN_CHANNEL, channel[0], 在进程池中的位置, PID}; 读事件处理函数 ngx_channel_handler()被调用;
    1> 获得 新子进程 在进程池中的位置;
    2> 保存 新子进程 的 channel[0];
    2> 保存 新子进程 的 PID.

点击(此处)折叠或打开

  1. {
  2.     ngx_channel_handler()
  3.     {
  4.         for ( ;; ) {
  5.             n=ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
  6.             switch (ch.command) {
  7.                 case NGX_CMD_QUIT:
  8.                     ngx_quit=1;
  9.                     break;

  10.                 case NGX_CMD_TERMINATE:
  11.                     ngx_terminate=1;
  12.                     break;

  13.                 case NGX_CMD_REOPEN:
  14.                     ngx_reopen=1;
  15.                     break;

  16.                 case NGX_CMD_OPEN_CHANNEL:
  17.                     ngx_processes[ch.slot].pid=ch.pid;
  18.                     ngx_processes[ch.slot].channel[0]=ch.fd;
  19.                     break;

  20.                 case NGX_CMD_CLOSE_CHANNEL:
  21.                     if (close(ngx_processes[ch.slot].channel[0]) == -1) {
  22.                     }
  23.                     ngx_processes[ch.slot].channel[0]=-1;
  24.                     break;
  25.             }
  26.         }
  27.     }
  28. }


5 执行 nginx -s reload 时
执行 nginx -s reload 的进程:
    从main函数开始一直执行到 

点击(此处)折叠或打开

  1. if (ngx_signal) {
  2.         return ngx_signal_process(cycle, ngx_signal);
  3.     }

    从nginx.pid文件中解析出当前的 master 进程PID, 向其发送 reload 信号

master:
    1> 接收到 reload 信号, 信号处理函数 ngx_signal_handler 中将 ngx_reconfigure=1;
    2> 进入 ngx_reconfigure 状态; 调用 ngx_init_cycle() 初始化环境,重新加载配置文件, 重新创建 worker进程, cache管理进程, cache加载进程(热代码忽略);
    3> 使用 UNIX域套接字 通知老的worker进程, cache管理进程(cache加载进程此时可能存在,也可能已经退出,因为在ngx_cache_loader_process_handler() {exit(0)}), NGX_CMD_QUIT;
        这里不通知的进程有: 刚刚创建的worker进程, cache管理进程, cache加载进程, 正在退出中且本次发送信号为 shutdown的进程, 热代码加载中的进程.
    4> 如果使用 UNIX域套接字发送 NGX_CMD_QUIT 失败 ,则使用 kill 发送 SIGQUIT, 将这些进程的属性 exiting=1; 如果发送信号时某进程已经退出,则将其属性 exited=1;
    5> 过N久之后, 这些被发送信号的进程会退出, master进程会收到内核发送来的 SIGCHLD,将 ngx_reap=1; 并调用 ngx_process_get_status()回收退出的子进程;
    6> 回收子进程 ngx_process_get_status();
    7> reload状态,也会进入 ngx_reap 状态, 这个状态是否会重新创建 那些老的可再生的子进程 呢?
        首先, 重新创建 老的可再生的子进程的条件是: 
            (ngx_processes[i].exited && ngx_processes[i].respawn && !ngx_processes[i].exiting && !ngx_terminate && !ngx_quit)
        reload状态,可以通过观察进程属性 respawn, exiting, exited 的值来判断是否会重新创建 那些老的可再生的子进程. 除了 cache loader 进程的respawn=0, 其他进程 respawn =1. 故只有 exited=1 && exiting=0 时才会重建.

        初始值 exiting=0, exited=0;
        reload状态, 通知老的子进程退出有三种情况:

点击(此处)折叠或打开

  1. {
  2.     /* 接受到 reload 信号: 1 "SIGHUP" ngx_signal_handler "reload" */
  3.     ngx_signal_handler()
  4.     {
  5.         switch (ngx_process) {
  6.             case NGX_PROCESS_MASTER:
  7.             case NGX_PROCESS_SINGLE:
  8.                 switch (signo) {
  9.                     //...
  10.                     case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
  11.                         ngx_reconfigure=1;
  12.                         action=", reconfiguring";
  13.                         break;
  14.                     case SIGCHLD:
  15.                         ngx_reap=1;
  16.                         break;

  17.                     //...
  18.                 }
  19.                     //...
  20.         }
  21.     }
  22.     ngx_master_process_cycle()
  23.     {
  24.         //...
  25.         for (;;)
  26.         {
  27.             if (ngx_reap)
  28.             {
  29.                 ngx_reap=0;
  30.                 ngx_reap_children(cycle);
  31.             }
  32.         if (ngx_reconfigure) {
  33.             ngx_reconfigure=0;

  34.             /* 热代码加载 */
  35.             if (ngx_new_binary) {
  36.                 ngx_start_worker_processes(cycle, ccf->worker_processes,
  37.                                            NGX_PROCESS_RESPAWN);
  38.                 ngx_start_cache_manager_processes(cycle, 0);
  39.                 ngx_noaccepting=0;

  40.                 continue;
  41.             }

  42.             /* 重新初始化,加载配置 */
  43.             cycle=ngx_init_cycle(cycle);

  44.             ngx_cycle=cycle;
  45.             ccf=(ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  46.                                                    ngx_core_module);
  47.             /* 重新创建新的 worker进程 */
  48.             ngx_start_worker_processes(cycle, ccf->worker_processes,
  49.                                        NGX_PROCESS_JUST_RESPAWN);
  50.             /* 重新创建新的 缓存池管理进程 和 缓存池加载进程 */
  51.             ngx_start_cache_manager_processes(cycle, 1);
  52.             /* 通知 */
  53.             ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  54.             {
  55.                 switch (signo) {

  56.                     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  57.                         ch.command=NGX_CMD_QUIT;
  58.                         break;

  59.                     default:
  60.                         ch.command=0;
  61.                 }
  62.                 for (i=0; i < ngx_last_process; i++) {

  63.                     /* 如果是 新创建的进程(NGX_PROCESS_JUST_RESPAWN), 正在退出的进程(ngx_processes[i]->exiting), 热代码加载的进程, 则不通知他们;
  64.                        否则通过 UNIX域套接字 告知.
  65.                      */
  66.                     if (ch.command) {
  67.                         if (ngx_write_channel(ngx_processes[i].channel[0],
  68.                                     &ch, sizeof(ngx_channel_t), cycle->log)
  69.                                 == NGX_OK)
  70.                         {
  71.                             if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  72.                                 ngx_processes[i].exiting=1; /* 将该进程的状态 exiting=1 */
  73.                             }

  74.                             continue;
  75.                         }
  76.                     }

  77.                     if (kill(ngx_processes[i].pid, signo) == -1) {
  78.                         if (err == NGX_ESRCH) { /* 该子进程进程为僵死进程 */
  79.                             ngx_processes[i].exited=1;
  80.                             ngx_processes[i].exiting=0;
  81.                             ngx_reap=1;
  82.                         }

  83.                         continue;
  84.                     }
  85.                     /* 除了 reopen 信号外, 其他信号都会使子进程退出, 这里将那些子进程的状态改为正在退出的状态.*/
  86.                     if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  87.                         ngx_processes[i].exiting=1;
  88.                     }
  89.                 }
  90.             }
  91.         }
  92.         }
  93.     }
  94.     ngx_process_get_status()
  95.     {
  96.         /* 循环回收 */
  97.         for ( ;; ) {

  98.             pid=waitpid(-1, &status, WNOHANG);

  99.             /* 如果子进程持有 accept 锁, 则释放. */
  100.             if (ngx_accept_mutex_ptr) {
  101.                 ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
  102.             }

  103.             /* 将该进程在master进程池中的属性 status=其退出码, exited=1, */
  104.             for (i=0; i < ngx_last_process; i++) {
  105.                 if (ngx_processes[i].pid == pid) {
  106.                     ngx_processes[i].status=status;
  107.                     ngx_processes[i].exited=1;
  108.                     process=ngx_processes[i].name;
  109.                     break;
  110.                 }
  111.             }

  112.             /* 打印日志: 如果子进程被信号中断,则打印出信号编号, 否则打印出其退出码*/
  113.             //...

  114.             /* nginx子进程有个 可再生(respawn, NGX_PROCESS_RESPAWN)属性: 如果该属性有效 master检测其退出后会再次创建它.
  115.                其中 worker进程, cache管理进程创建后,对应的 ngx_processes[i]->respawn=1; cache加载进程 ngx_processes[i]->respawn=0;意思推出后不需要再次创建它.
  116.                子进程的退出方式有:
  117.                被信号中断
  118.                自身退出,退出码 0 对应 cache 加载进程
  119.                自身退出,退出码 2 对应reload时,被通知的哪些旧的 worker进程, cache管理进程, cache加载进程(如果它reload时它还存在)退出时的退出码
  120.                这里就是使用这中机制来确定 master回收这些进程时,是否重新创建它.

  121.                退出码为2且拥有可再生权限,说明在重新加载配置文件, 这些退出的进程无须再创建他们, 将其 respawn=0;
  122.              */
  123.             if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
  124.                 ngx_processes[i].respawn=0;
  125.             }
  126.         }
  127.     }
  128.     ngx_reap_children()
  129.     {
  130.         ch.command=NGX_CMD_CLOSE_CHANNEL;
  131.         for (i=0; i < ngx_last_process; i++) {
  132.             if (ngx_processes[i].exited) {
  133.                 if (!ngx_processes[i].detached) {
  134.                     /* 清理子进程的 UNIX域套接字 资源, 通过 UNIX域套接字告知其他存活子进程 NGX_CMD_CLOSE_CHANNEL */
  135.                 }
  136.                 //...
  137.             } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
  138.                 live=1;
  139.             }
  140.         }

  141.         return live;
  142.     }

  143. }


点击(此处)折叠或打开

  1. {
  2.     ngx_channel_handler()
  3.     {
  4.         for ( ;; ) {
  5.             n=ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
  6.             switch (ch.command) {

  7.                 case NGX_CMD_QUIT:
  8.                         ngx_quit=1;
  9.                             break;
  10.             }
  11.         }
  12.     }
  13.     ngx_signal_handler()
  14.     {
  15.         switch (ngx_process) {
  16.             //...
  17.             case NGX_PROCESS_WORKER:
  18.             case NGX_PROCESS_HELPER:
  19.                 switch (signo) {
  20.                     //...
  21.                     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  22.                         ngx_quit=1;
  23.                         action=", shutting down";
  24.                         break;
  25.                         //...
  26.                 }
  27.                 //...
  28.                 break;
  29.         }
  30.     }
  31.     ngx_worker_process_cycle()
  32.     {
  33.         if (ngx_exiting) {
  34.             c=cycle->connections;
  35.             for (cycle->connection) {
  36.                 if (c[i].fd != -1 && c[i].idle) {
  37.                     c[i].close=1;
  38.                     c[i].read->handler(c[i].read);
  39.                 }
  40.             }
  41.             if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
  42.             {
  43.                 ngx_worker_process_exit(cycle);
  44.             }
  45.         }

  46.         if (ngx_quit) {
  47.             ngx_quit=0;
  48.             ngx_setproctitle("worker process is shutting down");

  49.             if (!ngx_exiting) {
  50.                 ngx_close_listening_sockets(cycle);
  51.                 ngx_exiting=1; /* 将 ngx_exiting 置为有效. */
  52.             }
  53.         }

  54.     }

  55. }





点击(此处)折叠或打开

  1. {
  2.     /* 接收信号 15 "SIGTERM" ngx_signal_handler "stop" */
  3.     ngx_signal_handler()
  4.     {
  5.         switch (ngx_process) {
  6.             case NGX_PROCESS_MASTER:
  7.             case NGX_PROCESS_SINGLE:
  8.                 switch (signo) {
  9.                     //...
  10.                     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
  11.                     case SIGINT:
  12.                         ngx_terminate=1;
  13.                         break;
  14.                     case SIGALRM:
  15.                         ngx_sigalrm=1;
  16.                         break;

  17.                     //...
  18.                 }
  19.                     //...
  20.         }
  21.     }
  22.     ngx_master_process_cycle()
  23.     {
  24.         for (;;)
  25.         {
  26.             if (delay) {
  27.                 if (ngx_sigalrm) {
  28.                     sigio=0;
  29.                     delay *= 2;
  30.                     ngx_sigalrm=0;
  31.                 }
  32.                 itv.it_interval.tv_sec=0;
  33.                 itv.it_interval.tv_usec=0;
  34.                 itv.it_value.tv_sec=delay / 1000;
  35.                 itv.it_value.tv_usec=(delay % 1000 ) * 1000;

  36.                 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
  37.                 }
  38.             }

  39.             sigsuspend(&set);

  40.             ngx_time_update();
  41.             if (ngx_reap) {
  42.                 ngx_reap = 0;
  43.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");

  44.                 live = ngx_reap_children(cycle);
  45.             }

  46.             if (!live && (ngx_terminate || ngx_quit)) {
  47.                 ngx_master_process_exit(cycle);
  48.             }


  49.         /* 退出机制: nginx -s stop
  50.            master 收到 SIGTERM 或者 SIGINT 时, 进入 ngx_terminate 状态, 然后给所有子进程通过 UNIX域套接字发送 发送 NGX_CMD_QUIT, 通过kill() SIGTERM 信号
  51.            给每个子进程预留 50 毫秒的退出时间, 使用setitmer()延迟 n*50 毫秒, 当 n*50 还有子进程未退出, 则延迟时间增加为 n*2*50 以此类推. 如果子进程在 1000 毫秒内还没有全部退出,则对还在运行的子进程发送 SIGKILL.
  52.            SIGKILL 是不能屏蔽也不能注册信号处理函数的信号, 动作为是 终止.
  53.          */
  54.             if (ngx_terminate) {
  55.                 if (delay == 0) {
  56.                     delay=50;
  57.                 }

  58.                 if (sigio) {
  59.                     sigio--;
  60.                     continue;
  61.                 }

  62.                 sigio=ccf->worker_processes + 2 /* cache processes */;

  63.                 if (delay > 1000) {
  64.                     ngx_signal_worker_processes(cycle, SIGKILL);
  65.                 } else {
  66.                     ngx_signal_worker_processes(cycle,
  67.                             ngx_signal_value(NGX_TERMINATE_SIGNAL));
  68.                 }

  69.                 continue;
  70.             }
  71.         }
  72.     }
  73. }



点击(此处)折叠或打开

  1. {
  2.     ngx_channel_handler()
  3.     {
  4.         for ( ;; ) {
  5.             n=ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
  6.             switch (ch.command) {

  7.                 case NGX_CMD_TERMINATE:
  8.                         ngx_terminate=1;
  9.                             break;
  10.             }
  11.         }
  12.     }
  13.     ngx_signal_handler()
  14.     {
  15.         switch (ngx_process) {
  16.             //...
  17.             case NGX_PROCESS_WORKER:
  18.             case NGX_PROCESS_HELPER:
  19.                 switch (signo) {
  20.                     //...
  21.                     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
  22.                         ngx_terminate=1;
  23.                         action=", shutting down";
  24.                         break;
  25.                         //...
  26.                 }
  27.                 //...
  28.         }
  29.     }
  30.     ngx_worker_process_cycle()
  31.     {
  32.         //...
  33.         ngx_process_events_and_timers(cycle);

  34.         if (ngx_terminate) {
  35.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");

  36.             ngx_worker_process_exit(cycle);
  37.         }
  38.     }
  39. }




点击(此处)折叠或打开

  1. {
  2.     // 接收信号 3 "SIGQUIT" ngx_signal_handler "quit"
  3.     ngx_signal_handler()
  4.     {
  5.         switch (ngx_process) {
  6.             case NGX_PROCESS_MASTER:
  7.             case NGX_PROCESS_SINGLE:
  8.                 switch (signo) {
  9.                     //...
  10.                     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  11.                         ngx_quit=1;
  12.                         break;
  13.                     //...
  14.                 }
  15.                     //...
  16.         }
  17.     }
  18.     ngx_master_process_cycle()
  19.     {
  20.         for (;;)
  21.         {
  22.             //...
  23.             sigsuspend(&set);

  24.             ngx_time_update();

  25.             if (ngx_reap) {
  26.                 ngx_reap = 0;
  27.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");

  28.                 live = ngx_reap_children(cycle);
  29.             }

  30.             if (!live && (ngx_terminate || ngx_quit)) {
  31.                 ngx_master_process_exit(cycle);
  32.             }

  33.             if (ngx_quit) {
  34.                 ngx_signal_worker_processes(cycle,
  35.                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));

  36.                 ls = cycle->listening.elts;
  37.                 for (n = 0; n < cycle->listening.nelts; n++) {
  38.                     if (ngx_close_socket(ls[n].fd) == -1) {
  39.                         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
  40.                                 ngx_close_socket_n " %V failed",
  41.                                 &ls[n].addr_text);
  42.                     }
  43.                 }
  44.                 cycle->listening.nelts = 0;

  45.                 continue;
  46.             }
  47.         }
  48.     }
  49. }



点击(此处)折叠或打开

  1. {
  2.     ngx_channel_handler()
  3.     {
  4.         for ( ;; ) {
  5.             n=ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
  6.             switch (ch.command) {

  7.                 case NGX_CMD_QUIT:
  8.                         ngx_quit=1;
  9.                             break;
  10.             }
  11.         }
  12.     }
  13.     ngx_signal_handler()
  14.     {
  15.         switch (ngx_process) {
  16.             //...
  17.             case NGX_PROCESS_WORKER:
  18.             case NGX_PROCESS_HELPER:
  19.                 switch (signo) {
  20.                     //...
  21.                     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  22.                         ngx_quit=1;
  23.                         action=", shutting down";
  24.                         break;
  25.                         //...
  26.                 }
  27.                 //...
  28.                 break;
  29.         }
  30.     }
  31.     ngx_worker_process_cycle()
  32.     {
  33.         if (ngx_exiting) {
  34.             c=cycle->connections;
  35.             for (cycle->connection) {
  36.                 if (c[i].fd != -1 && c[i].idle) {
  37.                     c[i].close=1;
  38.                     c[i].read->handler(c[i].read);
  39.                 }
  40.             }
  41.             if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
  42.             {
  43.                 ngx_worker_process_exit(cycle);
  44.             }
  45.         }

  46.         if (ngx_quit) {
  47.             ngx_quit=0;
  48.             ngx_setproctitle("worker process is shutting down");

  49.             if (!ngx_exiting) {
  50.                 ngx_close_listening_sockets(cycle);
  51.                 ngx_exiting=1; /* 将 ngx_exiting 置为有效. */
  52.             }
  53.         }

  54.     }
  55. }





点击(此处)折叠或打开

  1. {
  2.     // 接收信号 10 "SIGUSR1" ngx_signal_handler "reopen"
  3.     ngx_signal_handler()
  4.     {
  5.         switch (ngx_process) {
  6.             case NGX_PROCESS_MASTER:
  7.             case NGX_PROCESS_SINGLE:
  8.                 switch (signo) {
  9.                     //...
  10.                     case ngx_signal_value(NGX_REOPEN_SIGNAL):
  11.                         ngx_reopen=1;
  12.                         break;
  13.                     //...
  14.                 }
  15.                     //...
  16.         }
  17.     }
  18.     ngx_master_process_cycle()
  19.     {
  20.         for (;;)
  21.         {
  22.             //...
  23.             sigsuspend(&set);

  24.             ngx_time_update();

  25.             if (ngx_reopen) {
  26.                 ngx_reopen = 0;
  27.                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  28.                 ngx_reopen_files(cycle, ccf->user);
  29.                 ngx_signal_worker_processes(cycle,
  30.                         ngx_signal_value(NGX_REOPEN_SIGNAL));
  31.             }
  32.         }
  33.     }
  34. }


点击(此处)折叠或打开

  1. {
  2.     ngx_channel_handler()
  3.     {
  4.         for ( ;; ) {
  5.             n=ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
  6.             switch (ch.command) {

  7.                 case NGX_CMD_REOPEN:
  8.                         ngx_reopen=1;
  9.                             break;
  10.             }
  11.         }
  12.     }
  13.     ngx_signal_handler()
  14.     {
  15.         switch (ngx_process) {
  16.             //...
  17.             case NGX_PROCESS_WORKER:
  18.             case NGX_PROCESS_HELPER:
  19.                 switch (signo) {
  20.                     //...
  21.                     case ngx_signal_value(NGX_REOPEN_SIGNAL):
  22.                         ngx_reopen=1;
  23.                         action=", shutting down";
  24.                         break;
  25.                         //...
  26.                 }
  27.                 //...
  28.                 break;
  29.         }
  30.     }
  31.     ngx_worker_process_cycle()
  32.     {
  33.         if (ngx_reopen) {
  34.             ngx_reopen = 0;
  35.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  36.             ngx_reopen_files(cycle, -1);
  37.         }
  38.     }
  39. }



点击(此处)折叠或打开

  1. {
  2.     ngx_signal_handler()
  3.     {
  4.         switch (ngx_process) {
  5.             case NGX_PROCESS_MASTER:
  6.             case NGX_PROCESS_SINGLE:
  7.                 switch (signo) {
  8.                     case SIGCHLD:
  9.                         ngx_reap=1;
  10.                         break;
  11.                 }
  12.         }

  13.         if (signo == SIGCHLD) {
  14.             ngx_process_get_status();
  15.         }
  16.     }
  17.     ngx_master_process_cycle()
  18.     {
  19.         for (;;)
  20.         {
  21.             if (ngx_reap)
  22.             {
  23.                 ngx_reap=0;
  24.                 live=ngx_reap_children(cycle);
  25.             }
  26.         }
  27.     }
  28.     ngx_reap_children()
  29.     {
  30.         ch.command=NGX_CMD_CLOSE_CHANNEL;
  31.         for (i=0; i < ngx_last_process; i++) {
  32.             if (ngx_processes[i].exited) {

  33.                 if (!ngx_processes[i].detached) {

  34.                     ngx_close_channel(ngx_processes[i].channel, cycle->log);

  35.                     ngx_processes[i].channel[0]=-1;
  36.                     ngx_processes[i].channel[1]=-1;

  37.                     ch.pid=ngx_processes[i].pid;
  38.                     ch.slot=i;

  39.                     for (n=0; n < ngx_last_process; n++) {
  40.                         if (ngx_processes[n].exited
  41.                                 || ngx_processes[n].pid == -1
  42.                                 || ngx_processes[n].channel[0] == -1)
  43.                         {
  44.                             continue;
  45.                         }
  46.                         ngx_write_channel(ngx_processes[n].channel[0],
  47.                                 &ch, sizeof(ngx_channel_t), cycle->log);
  48.                     }
  49.                 }

  50.                 if (ngx_processes[i].respawn
  51.                         && !ngx_processes[i].exiting
  52.                         && !ngx_terminate
  53.                         && !ngx_quit)
  54.                 {
  55.                     if (ngx_spawn_process(cycle, ngx_processes[i].proc,
  56.                                 ngx_processes[i].data,
  57.                                 ngx_processes[i].name, i)
  58.                             == NGX_INVALID_PID)
  59.                     {
  60.                         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  61.                                 "could not respawn %s",
  62.                                 ngx_processes[i].name);
  63.                         continue;
  64.                     }


  65.                     ch.command=NGX_CMD_OPEN_CHANNEL;
  66.                     ch.pid=ngx_processes[ngx_process_slot].pid;
  67.                     ch.slot=ngx_process_slot;
  68.                     ch.fd=ngx_processes[ngx_process_slot].channel[0];

  69.                     ngx_pass_open_channel(cycle, &ch);

  70.                     live=1;

  71.                     continue;
  72.                 }

  73.                 if (ngx_processes[i].pid == ngx_new_binary) {

  74.                     ccf=(ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  75.                             ngx_core_module);

  76.                     if (ngx_rename_file((char *) ccf->oldpid.data,
  77.                                 (char *) ccf->pid.data)
  78.                             != NGX_OK)
  79.                     {
  80.                         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  81.                                 ngx_rename_file_n " %s back to %s failed "
  82.                                 "after the new binary process \"%s\" exited",
  83.                                 ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
  84.                     }

  85.                     ngx_new_binary=0;
  86.                     if (ngx_noaccepting) {
  87.                         ngx_restart=1;
  88.                         ngx_noaccepting=0;
  89.                     }
  90.                 }

  91.                 if (i == ngx_last_process - 1) {
  92.                     ngx_last_process--;

  93.                 } else {
  94.                     ngx_processes[i].pid=-1;
  95.                 }

  96.             } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
  97.                 live=1;
  98.             }
  99.         }

  100.         return live;
  101.     }
  102. }




阅读(4213) | 评论(0) | 转发(0) |
0

上一篇:shell 获取域名或IP地址的地理位置

下一篇:没有了

给主人留下些什么吧!~~