Chinaunix首页 | 论坛 | 博客
  • 博客访问: 298438
  • 博文数量: 63
  • 博客积分: 814
  • 博客等级: 军士长
  • 技术积分: 700
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-09 15:46
文章分类

全部博文(63)

文章存档

2017年(1)

2016年(4)

2015年(13)

2014年(9)

2012年(3)

2011年(33)

分类: LINUX

2011-05-20 17:48:15


     nginx 进程采用master worker(父子) 模型,master接收信号,对子进程进行控制和重启,这里我就拿子进程core 掉为例 。

    子进程Core 父进程会收到SIGCHLD 信号,所以master 做出判断,对于core的子进程进行重启。
    下面就是实例代码,我将nginx 中这块代码抽出来,进行了调试。gcc -o test  workers.c
    
     程序中我会不断的产生core,让空指针 *p=100 ;  所以此进程会core ,master 进程收到SIGCHLD 信号,后,设置相应全局变量ngx_reap , 然后master 会重启此进程。

    函数ngx_process_get_status对退出的子进程进行回收waitpid(); 不然子进程变成僵尸进程

    注意master 在启动时应阻塞要处理的一些信号,不然sigsuspend之前发生信号,将会收不到。把下面的代码去掉,就能看到。子进程一启动就core (sigsuspend之前),  但master 会丢失此信号。所以nginx 在此阻塞了一些信号的发生。我的例子只加入一部分信号。

  1. if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
  2.         printf("sigprocmask failed \n");
  3.     }
     当初的疑问:在处理SIGCHLD 时,有如下代码,当时不太明白,是这样,对已退出的进程判断,获得accept 锁的,要进行解锁。锁机制下一步会详细看。
  1.         if (ngx_accept_mutex_ptr)
  2.         {
  3.             ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
  4.         }

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdint.h>
  5. #include <signal.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <sys/wait.h>
  9. typedef intptr_t ngx_int_t;
  10. typedef uintptr_t ngx_uint_t;
  11. typedef int* ngx_log_t;
  12. typedef pid_t ngx_pid_t;
  13. typedef int ngx_cycle_t;
  14. typedef int ngx_err_t;

  15. ngx_int_t ngx_last_process;
  16. ngx_int_t ngx_process_slot;

  17. typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data);

  18. #define NGX_OK 0

  19. #define NGX_PROCESS_SINGLE 0
  20. #define NGX_PROCESS_MASTER 1
  21. #define NGX_PROCESS_SIGNALLER 2
  22. #define NGX_PROCESS_WORKER 3
  23. #define NGX_PROCESS_HELPER 4

  24. #define NGX_MAX_PROCESSES 1024
  25. #define NGX_INVALID_PID -1

  26. #define NGX_PROCESS_NORESPAWN -1
  27. #define NGX_PROCESS_JUST_SPAWN -2
  28. #define NGX_PROCESS_RESPAWN -3
  29. #define NGX_PROCESS_JUST_RESPAWN -4
  30. #define NGX_PROCESS_DETACHED -5

  31. #define NGX_EINTR EINTR
  32. #define NGX_ECHILD ECHILD

  33. #define ngx_errno errno
  34. #define ngx_socket_errno errno
  35. #define ngx_set_errno(err) errno = err
  36. #define ngx_set_socket_errno(err) errno = err


  37. typedef struct {
  38.     int signo;
  39.     char *signame;
  40.     char *name;
  41.     void (*handler)(int signo);
  42. } ngx_signal_t;

  43. typedef struct {
  44.     ngx_pid_t pid;
  45.     int status;
  46.     //ngx_socket_t channel[2];

  47.     ngx_spawn_proc_pt proc;
  48.     void *data;
  49.     char *name;

  50.     unsigned respawn:1;
  51.     unsigned just_spawn:1;
  52.     unsigned detached:1;
  53.     unsigned exiting:1;
  54.     unsigned exited:1;
  55. } ngx_process_t;

  56. ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
  57. int ngx_process;


  58. sig_atomic_t ngx_reap;
  59. sig_atomic_t ngx_sigio;
  60. sig_atomic_t ngx_sigalrm;
  61. sig_atomic_t ngx_terminate;
  62. sig_atomic_t ngx_quit;
  63. sig_atomic_t ngx_debug_quit;
  64. ngx_uint_t ngx_exiting;
  65. sig_atomic_t ngx_reconfigure;
  66. sig_atomic_t ngx_reopen;


  67. void ngx_signal_handler(int signo);

  68. ngx_signal_t signals[] =
  69. {
  70.     { SIGALRM, "SIGALRM", "", ngx_signal_handler },

  71.     { SIGINT, "SIGINT", "", ngx_signal_handler },

  72.     { SIGIO, "SIGIO", "", ngx_signal_handler },

  73.     { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },

  74.     { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN },

  75.     { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN },

  76.     { 0, NULL, "", NULL }
  77. };
  78. static void
  79. ngx_process_get_status(void)
  80. {
  81.     int status;
  82.     char *process;
  83.     ngx_pid_t pid;
  84.     ngx_err_t err;
  85.     ngx_int_t i;
  86.     ngx_uint_t one;

  87.     one = 0;

  88.     for ( ;; ) {
  89.         pid = waitpid(-1, &status, WNOHANG);

  90.         if (pid == 0)
  91.         {
  92.             return;
  93.         }

  94.         if (pid == -1)
  95.         {
  96.             err = ngx_errno;
  97.             if (err == NGX_EINTR) {
  98.                 continue;
  99.             }

  100.             if (err == NGX_ECHILD && one) {
  101.                 return;
  102.             }
  103.             //ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,"waitpid() failed");
  104.             return;
  105.         }
  106. /*
  107.         if (ngx_accept_mutex_ptr)
  108.         {
  109.             ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
  110.         }

  111. */
  112.         one = 1;
  113.         process = "unknown process";

  114.         for (i = 0; i < ngx_last_process; i++) {
  115.             if (ngx_processes[i].pid == pid) {
  116.                 ngx_processes[i].status = status;
  117.                 ngx_processes[i].exited = 1;
  118.                 process = ngx_processes[i].name;
  119.                 break;
  120.             }
  121.         }

  122.         if (WTERMSIG(status))
  123.         {

  124.         }
  125.         else
  126.         {
  127.             /*ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
  128.                     "%s %P exited with code %d",
  129.                     process, pid, WEXITSTATUS(status));
  130.             */
  131.         }

  132.         if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn)
  133.         {
  134.            /* ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  135.                     "%s %P exited with fatal code %d "
  136.                     "and can not be respawn",
  137.                     process, pid, WEXITSTATUS(status));
  138.            */
  139.             printf("status ==2 \n");
  140.             ngx_processes[i].respawn = 0;
  141.         }
  142.     }
  143. }

  144. void
  145. ngx_signal_handler(int signo)
  146. {
  147.     char *action;
  148.     ngx_int_t ignore;
  149.     ngx_signal_t *sig;

  150.     for (sig = signals; sig->signo != 0; sig++) {
  151.         if (sig->signo == signo) {
  152.             break;
  153.         }
  154.     }

  155.     action = "";
  156.     switch (ngx_process) {

  157.         case NGX_PROCESS_MASTER:
  158.         case NGX_PROCESS_SINGLE:
  159.             switch (signo) {

  160.                 case SIGALRM:
  161.                     ngx_sigalrm = 1;
  162.                     break;

  163.                 case SIGIO:
  164.                     ngx_sigio = 1;
  165.                     break;

  166.                 case SIGCHLD:
  167.                     {printf("------------SIGCHLD \n");ngx_reap = 1;}
  168.                     break;
  169.             }

  170.             break;

  171.         case NGX_PROCESS_WORKER:
  172.         case NGX_PROCESS_HELPER:
  173.             switch (signo) {

  174.                 case SIGIO:
  175.                     action = ", ignoring";
  176.                     break;
  177.             }

  178.             break;
  179.     }
  180.     printf("****** signal =[%d] \n",signo);
  181.     if (signo == SIGCHLD)
  182.     {
  183.         ngx_process_get_status();
  184.     }

  185. }

  186. ngx_int_t
  187. ngx_init_signals(ngx_log_t *log)
  188. {
  189.     ngx_signal_t *sig;
  190.     struct sigaction sa;

  191.     for (sig = signals; sig->signo != 0; sig++) {
  192.         //ngx_memzero(&sa, sizeof(struct sigaction));
  193.         memset(&sa,sizeof(struct sigaction),0);
  194.         sa.sa_handler = sig->handler;
  195.         sigemptyset(&sa.sa_mask);
  196.         if (sigaction(sig->signo, &sa, NULL) == -1)
  197.         {
  198.             /*ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
  199.                     "sigaction(%s) failed", sig->signame);
  200.             return NGX_ERROR;
  201.             */
  202.             printf("error \n");
  203.             return -1;
  204.         }
  205.     }

  206.     return NGX_OK;
  207. }

  208. static void
  209. ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type);
  210. static ngx_uint_t
  211. ngx_reap_children(ngx_cycle_t *cycle);

  212. void
  213. ngx_master_process_cycle(ngx_cycle_t *cycle)
  214. {
  215.     sigset_t set;
  216.     sigemptyset(&set);
  217.     ngx_uint_t live;
  218.     sigemptyset(&set);
  219.     
  220.     sigaddset(&set, SIGCHLD);
  221.     sigaddset(&set, SIGALRM);
  222.     sigaddset(&set, SIGIO);
  223.     sigaddset(&set, SIGINT);

  224.     if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
  225.         /*ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  226.                 "sigprocmask() failed");
  227.         */
  228.         printf("sigprocmask failed \n");
  229.     }

  230.     sigemptyset(&set);

  231.     ngx_start_worker_processes(NULL,4,NGX_PROCESS_RESPAWN);
  232.     for ( ;; )
  233.     {

  234.         sigsuspend(&set);

  235.         if(ngx_reap)
  236.         {
  237.             ngx_reap=0;
  238.             printf("****some worker process exit !\n");

  239.             //sleep(5);
  240.             /*
  241.             if(ngx_spawn_process(cycle, ngx_processes[0].proc,
  242.                         ngx_processes[0].data,
  243.                         ngx_processes[0].name, 0)
  244.                     == NGX_INVALID_PID)
  245.             {
  246.                 printf("*****spawn_process error \n");
  247.                 continue;
  248.             }
  249.             */

  250.             live = ngx_reap_children(cycle);

  251.             printf("******restart Process \n");
  252.         }
  253.     }
  254. }
  255. static ngx_uint_t
  256. ngx_reap_children(ngx_cycle_t *cycle)
  257. {
  258.     ngx_int_t i;
  259.     for (i = 0; i < ngx_last_process; i++)
  260.     {
  261.         if (ngx_processes[i].pid == -1)
  262.         {
  263.             continue;
  264.         }
  265.         if (ngx_processes[i].exited)
  266.         {

  267.             if (!ngx_processes[i].detached)
  268.             {
  269.             }

  270.             if (ngx_processes[i].respawn
  271.                     && !ngx_processes[i].exiting
  272.                     && !ngx_terminate
  273.                     && !ngx_quit)
  274.             {
  275.                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
  276.                             ngx_processes[i].data,
  277.                             ngx_processes[i].name, i)
  278.                         == NGX_INVALID_PID)
  279.                 {
  280.                     /*ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  281.                             "can not respawn %s", ngx_processes[i].name);*/
  282.                     continue;
  283.                 }
  284.             }
  285.         }
  286.     }
  287. }

  288. ngx_pid_t
  289. ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
  290.             char *name, ngx_int_t respawn)
  291. {
  292.     u_long on;
  293.     ngx_pid_t pid;
  294.     ngx_int_t s;

  295.     if (respawn >= 0)
  296.     {
  297.         s = respawn;
  298.     }
  299.     else
  300.     {
  301.         for (s = 0; s < ngx_last_process; s++) {
  302.             if (ngx_processes[s].pid == -1) {
  303.                 break;
  304.             }
  305.         }

  306.         if (s == NGX_MAX_PROCESSES) {
  307.             /*ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  308.                     "no more than %d processes can be spawned",
  309.                     NGX_MAX_PROCESSES);*/
  310.             return NGX_INVALID_PID;
  311.         }
  312.     }
  313.     ngx_process_slot = s;
  314.     printf("process_slot = %d \n",ngx_process_slot);
  315.     pid = fork();
  316.     switch (pid) {
  317.         case -1:
  318.             /*ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  319.                     "fork() failed while spawning \"%s\"", name);
  320.             ngx_close_channel(ngx_processes[s].channel, cycle->log);*/
  321.             return NGX_INVALID_PID;
  322.         case 0:
  323.             //ngx_pid = ngx_getpid();
  324.             proc(cycle, data);
  325.             break;
  326.         default:
  327.             break;
  328.     }

  329.     //ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);

  330.     ngx_processes[s].pid = pid;
  331.     ngx_processes[s].exited = 0;

  332.     if (respawn >= 0) {
  333.         return pid;
  334.     }

  335.     ngx_processes[s].proc = proc;
  336.     ngx_processes[s].data = data;
  337.     ngx_processes[s].name = name;
  338.     ngx_processes[s].exiting = 0;
  339.     switch (respawn) {

  340.         case NGX_PROCESS_NORESPAWN:
  341.             ngx_processes[s].respawn = 0;
  342.             ngx_processes[s].just_spawn = 0;
  343.             ngx_processes[s].detached = 0;
  344.             break;

  345.         case NGX_PROCESS_JUST_SPAWN:
  346.             ngx_processes[s].respawn = 0;
  347.             ngx_processes[s].just_spawn = 1;
  348.             ngx_processes[s].detached = 0;
  349.             break;

  350.         case NGX_PROCESS_RESPAWN:
  351.             ngx_processes[s].respawn = 1;
  352.             ngx_processes[s].just_spawn = 0;
  353.             ngx_processes[s].detached = 0;
  354.             break;

  355.         case NGX_PROCESS_JUST_RESPAWN:
  356.             ngx_processes[s].respawn = 1;
  357.             ngx_processes[s].just_spawn = 1;
  358.             ngx_processes[s].detached = 0;
  359.             break;

  360.         case NGX_PROCESS_DETACHED:
  361.             ngx_processes[s].respawn = 0;
  362.             ngx_processes[s].just_spawn = 0;
  363.             ngx_processes[s].detached = 1;
  364.             break;
  365.     }

  366.     if (s == ngx_last_process) {
  367.         ngx_last_process++;
  368.     }
  369.     return pid;
  370. }
  371. static void
  372. ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
  373. {
  374.     ngx_process = NGX_PROCESS_WORKER;
  375.     ngx_int_t corepid;
  376.     if(ngx_process_slot==0) corepid=getpid();
  377.     
  378.     char *p;
  379.     //ngx_worker_process_init(cycle, 1);
  380.     for ( ;; )
  381.     {
  382.         if (ngx_exiting)
  383.         {
  384.             printf("exiting \n");
  385.             exit(0);
  386.         }
  387.         if(ngx_reopen)
  388.         {
  389.             printf("reopen \n");
  390.             exit(0);
  391.         }
  392.         printf("pid=%d corepid=%d\n",getpid(),corepid);
  393.         if(getpid() == corepid) {sleep(1);printf("before core happen [%d]\n",corepid); *p=100;}
  394.         sleep(1);
  395.     }
  396. }
  397. static void
  398. ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
  399. {
  400.     ngx_int_t i;
  401.     //ngx_channel_t ch;
  402.     //ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
  403.     //ch.command = NGX_CMD_OPEN_CHANNEL;

  404.     for (i = 0; i < n; i++)
  405.     {
  406.         //cpu_affinity = ngx_get_cpu_affinity(i);
  407.         ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
  408.                 "worker process", type);

  409.         //ch.pid = ngx_processes[ngx_process_slot].pid;
  410.         //ch.slot = ngx_process_slot;
  411.         //ch.fd = ngx_processes[ngx_process_slot].channel[0];

  412.         //ngx_pass_open_channel(cycle, &ch);
  413.     }
  414. }
  415. int main()
  416. {
  417.     ngx_process = NGX_PROCESS_MASTER;
  418.     ngx_init_signals(NULL);
  419.     printf("hello worker program !!\n");
  420.     ngx_master_process_cycle(NULL);

  421.     return 0;
  422. }

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

上一篇:sigsuspend

下一篇:Learn DLL (One) 【收藏】

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