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 在此阻塞了一些信号的发生。我的例子只加入一部分信号。
- if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
-
printf("sigprocmask failed \n");
-
}
当初的疑问:在处理SIGCHLD 时,有如下代码,当时不太明白,是这样,对已退出的进程判断,获得accept 锁的,要进行解锁。锁机制下一步会详细看。
-
if (ngx_accept_mutex_ptr)
-
{
-
ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
-
}
- #include <stdlib.h>
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <stdint.h>
-
#include <signal.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <sys/wait.h>
-
typedef intptr_t ngx_int_t;
-
typedef uintptr_t ngx_uint_t;
-
typedef int* ngx_log_t;
-
typedef pid_t ngx_pid_t;
-
typedef int ngx_cycle_t;
-
typedef int ngx_err_t;
-
-
ngx_int_t ngx_last_process;
-
ngx_int_t ngx_process_slot;
-
-
typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data);
-
-
#define NGX_OK 0
-
-
#define NGX_PROCESS_SINGLE 0
-
#define NGX_PROCESS_MASTER 1
-
#define NGX_PROCESS_SIGNALLER 2
-
#define NGX_PROCESS_WORKER 3
-
#define NGX_PROCESS_HELPER 4
-
-
#define NGX_MAX_PROCESSES 1024
-
#define NGX_INVALID_PID -1
-
-
#define NGX_PROCESS_NORESPAWN -1
-
#define NGX_PROCESS_JUST_SPAWN -2
-
#define NGX_PROCESS_RESPAWN -3
-
#define NGX_PROCESS_JUST_RESPAWN -4
-
#define NGX_PROCESS_DETACHED -5
-
-
#define NGX_EINTR EINTR
-
#define NGX_ECHILD ECHILD
-
-
#define ngx_errno errno
-
#define ngx_socket_errno errno
-
#define ngx_set_errno(err) errno = err
-
#define ngx_set_socket_errno(err) errno = err
-
-
-
typedef struct {
-
int signo;
-
char *signame;
-
char *name;
-
void (*handler)(int signo);
-
} ngx_signal_t;
-
-
typedef struct {
-
ngx_pid_t pid;
-
int status;
-
//ngx_socket_t channel[2];
-
-
ngx_spawn_proc_pt proc;
-
void *data;
-
char *name;
-
-
unsigned respawn:1;
-
unsigned just_spawn:1;
-
unsigned detached:1;
-
unsigned exiting:1;
-
unsigned exited:1;
-
} ngx_process_t;
-
-
ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
-
int ngx_process;
-
-
-
sig_atomic_t ngx_reap;
-
sig_atomic_t ngx_sigio;
-
sig_atomic_t ngx_sigalrm;
-
sig_atomic_t ngx_terminate;
-
sig_atomic_t ngx_quit;
-
sig_atomic_t ngx_debug_quit;
-
ngx_uint_t ngx_exiting;
-
sig_atomic_t ngx_reconfigure;
-
sig_atomic_t ngx_reopen;
-
-
-
void ngx_signal_handler(int signo);
-
-
ngx_signal_t signals[] =
-
{
-
{ SIGALRM, "SIGALRM", "", ngx_signal_handler },
-
-
{ SIGINT, "SIGINT", "", ngx_signal_handler },
-
-
{ SIGIO, "SIGIO", "", ngx_signal_handler },
-
-
{ SIGCHLD, "SIGCHLD", "", ngx_signal_handler },
-
-
{ SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN },
-
-
{ SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN },
-
-
{ 0, NULL, "", NULL }
-
};
-
static void
-
ngx_process_get_status(void)
-
{
-
int status;
-
char *process;
-
ngx_pid_t pid;
-
ngx_err_t err;
-
ngx_int_t i;
-
ngx_uint_t one;
-
-
one = 0;
-
-
for ( ;; ) {
-
pid = waitpid(-1, &status, WNOHANG);
-
-
if (pid == 0)
-
{
-
return;
-
}
-
-
if (pid == -1)
-
{
-
err = ngx_errno;
-
if (err == NGX_EINTR) {
-
continue;
-
}
-
-
if (err == NGX_ECHILD && one) {
-
return;
-
}
-
//ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,"waitpid() failed");
-
return;
-
}
-
/*
-
if (ngx_accept_mutex_ptr)
-
{
-
ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
-
}
-
-
*/
-
one = 1;
-
process = "unknown process";
-
-
for (i = 0; i < ngx_last_process; i++) {
-
if (ngx_processes[i].pid == pid) {
-
ngx_processes[i].status = status;
-
ngx_processes[i].exited = 1;
-
process = ngx_processes[i].name;
-
break;
-
}
-
}
-
-
if (WTERMSIG(status))
-
{
-
-
}
-
else
-
{
-
/*ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
-
"%s %P exited with code %d",
-
process, pid, WEXITSTATUS(status));
-
*/
-
}
-
-
if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn)
-
{
-
/* ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
-
"%s %P exited with fatal code %d "
-
"and can not be respawn",
-
process, pid, WEXITSTATUS(status));
-
*/
-
printf("status ==2 \n");
-
ngx_processes[i].respawn = 0;
-
}
-
}
-
}
-
-
void
-
ngx_signal_handler(int signo)
-
{
-
char *action;
-
ngx_int_t ignore;
-
ngx_signal_t *sig;
-
-
for (sig = signals; sig->signo != 0; sig++) {
-
if (sig->signo == signo) {
-
break;
-
}
-
}
-
-
action = "";
-
switch (ngx_process) {
-
-
case NGX_PROCESS_MASTER:
-
case NGX_PROCESS_SINGLE:
-
switch (signo) {
-
-
case SIGALRM:
-
ngx_sigalrm = 1;
-
break;
-
-
case SIGIO:
-
ngx_sigio = 1;
-
break;
-
-
case SIGCHLD:
-
{printf("------------SIGCHLD \n");ngx_reap = 1;}
-
break;
-
}
-
-
break;
-
-
case NGX_PROCESS_WORKER:
-
case NGX_PROCESS_HELPER:
-
switch (signo) {
-
-
case SIGIO:
-
action = ", ignoring";
-
break;
-
}
-
-
break;
-
}
-
printf("****** signal =[%d] \n",signo);
-
if (signo == SIGCHLD)
-
{
-
ngx_process_get_status();
-
}
-
-
}
-
-
ngx_int_t
-
ngx_init_signals(ngx_log_t *log)
-
{
-
ngx_signal_t *sig;
-
struct sigaction sa;
-
-
for (sig = signals; sig->signo != 0; sig++) {
-
//ngx_memzero(&sa, sizeof(struct sigaction));
-
memset(&sa,sizeof(struct sigaction),0);
-
sa.sa_handler = sig->handler;
-
sigemptyset(&sa.sa_mask);
-
if (sigaction(sig->signo, &sa, NULL) == -1)
-
{
-
/*ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
-
"sigaction(%s) failed", sig->signame);
-
return NGX_ERROR;
-
*/
-
printf("error \n");
-
return -1;
-
}
-
}
-
-
return NGX_OK;
-
}
-
-
static void
-
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type);
-
static ngx_uint_t
-
ngx_reap_children(ngx_cycle_t *cycle);
-
-
void
-
ngx_master_process_cycle(ngx_cycle_t *cycle)
-
{
-
sigset_t set;
-
sigemptyset(&set);
-
ngx_uint_t live;
-
sigemptyset(&set);
-
-
sigaddset(&set, SIGCHLD);
-
sigaddset(&set, SIGALRM);
-
sigaddset(&set, SIGIO);
-
sigaddset(&set, SIGINT);
-
-
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
-
/*ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
-
"sigprocmask() failed");
-
*/
-
printf("sigprocmask failed \n");
-
}
-
-
sigemptyset(&set);
-
-
ngx_start_worker_processes(NULL,4,NGX_PROCESS_RESPAWN);
-
for ( ;; )
-
{
-
-
sigsuspend(&set);
-
-
if(ngx_reap)
-
{
-
ngx_reap=0;
-
printf("****some worker process exit !\n");
-
-
//sleep(5);
-
/*
-
if(ngx_spawn_process(cycle, ngx_processes[0].proc,
-
ngx_processes[0].data,
-
ngx_processes[0].name, 0)
-
== NGX_INVALID_PID)
-
{
-
printf("*****spawn_process error \n");
-
continue;
-
}
-
*/
-
-
live = ngx_reap_children(cycle);
-
-
printf("******restart Process \n");
-
}
-
}
-
}
-
static ngx_uint_t
-
ngx_reap_children(ngx_cycle_t *cycle)
-
{
-
ngx_int_t i;
-
for (i = 0; i < ngx_last_process; i++)
-
{
-
if (ngx_processes[i].pid == -1)
-
{
-
continue;
-
}
-
if (ngx_processes[i].exited)
-
{
-
-
if (!ngx_processes[i].detached)
-
{
-
}
-
-
if (ngx_processes[i].respawn
-
&& !ngx_processes[i].exiting
-
&& !ngx_terminate
-
&& !ngx_quit)
-
{
-
if (ngx_spawn_process(cycle, ngx_processes[i].proc,
-
ngx_processes[i].data,
-
ngx_processes[i].name, i)
-
== NGX_INVALID_PID)
-
{
-
/*ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
-
"can not respawn %s", ngx_processes[i].name);*/
-
continue;
-
}
-
}
-
}
-
}
-
}
-
-
ngx_pid_t
-
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
-
char *name, ngx_int_t respawn)
-
{
-
u_long on;
-
ngx_pid_t pid;
-
ngx_int_t s;
-
-
if (respawn >= 0)
-
{
-
s = respawn;
-
}
-
else
-
{
-
for (s = 0; s < ngx_last_process; s++) {
-
if (ngx_processes[s].pid == -1) {
-
break;
-
}
-
}
-
-
if (s == NGX_MAX_PROCESSES) {
-
/*ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
-
"no more than %d processes can be spawned",
-
NGX_MAX_PROCESSES);*/
-
return NGX_INVALID_PID;
-
}
-
}
-
ngx_process_slot = s;
-
printf("process_slot = %d \n",ngx_process_slot);
-
pid = fork();
-
switch (pid) {
-
case -1:
-
/*ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
-
"fork() failed while spawning \"%s\"", name);
-
ngx_close_channel(ngx_processes[s].channel, cycle->log);*/
-
return NGX_INVALID_PID;
-
case 0:
-
//ngx_pid = ngx_getpid();
-
proc(cycle, data);
-
break;
-
default:
-
break;
-
}
-
-
//ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);
-
-
ngx_processes[s].pid = pid;
-
ngx_processes[s].exited = 0;
-
-
if (respawn >= 0) {
-
return pid;
-
}
-
-
ngx_processes[s].proc = proc;
-
ngx_processes[s].data = data;
-
ngx_processes[s].name = name;
-
ngx_processes[s].exiting = 0;
-
switch (respawn) {
-
-
case NGX_PROCESS_NORESPAWN:
-
ngx_processes[s].respawn = 0;
-
ngx_processes[s].just_spawn = 0;
-
ngx_processes[s].detached = 0;
-
break;
-
-
case NGX_PROCESS_JUST_SPAWN:
-
ngx_processes[s].respawn = 0;
-
ngx_processes[s].just_spawn = 1;
-
ngx_processes[s].detached = 0;
-
break;
-
-
case NGX_PROCESS_RESPAWN:
-
ngx_processes[s].respawn = 1;
-
ngx_processes[s].just_spawn = 0;
-
ngx_processes[s].detached = 0;
-
break;
-
-
case NGX_PROCESS_JUST_RESPAWN:
-
ngx_processes[s].respawn = 1;
-
ngx_processes[s].just_spawn = 1;
-
ngx_processes[s].detached = 0;
-
break;
-
-
case NGX_PROCESS_DETACHED:
-
ngx_processes[s].respawn = 0;
-
ngx_processes[s].just_spawn = 0;
-
ngx_processes[s].detached = 1;
-
break;
-
}
-
-
if (s == ngx_last_process) {
-
ngx_last_process++;
-
}
-
return pid;
-
}
-
static void
-
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
-
{
-
ngx_process = NGX_PROCESS_WORKER;
-
ngx_int_t corepid;
-
if(ngx_process_slot==0) corepid=getpid();
-
-
char *p;
-
//ngx_worker_process_init(cycle, 1);
-
for ( ;; )
-
{
-
if (ngx_exiting)
-
{
-
printf("exiting \n");
-
exit(0);
-
}
-
if(ngx_reopen)
-
{
-
printf("reopen \n");
-
exit(0);
-
}
-
printf("pid=%d corepid=%d\n",getpid(),corepid);
-
if(getpid() == corepid) {sleep(1);printf("before core happen [%d]\n",corepid); *p=100;}
-
sleep(1);
-
}
-
}
-
static void
-
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
-
{
-
ngx_int_t i;
-
//ngx_channel_t ch;
-
//ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
-
//ch.command = NGX_CMD_OPEN_CHANNEL;
-
-
for (i = 0; i < n; i++)
-
{
-
//cpu_affinity = ngx_get_cpu_affinity(i);
-
ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
-
"worker process", type);
-
-
//ch.pid = ngx_processes[ngx_process_slot].pid;
-
//ch.slot = ngx_process_slot;
-
//ch.fd = ngx_processes[ngx_process_slot].channel[0];
-
-
//ngx_pass_open_channel(cycle, &ch);
-
}
-
}
-
int main()
-
{
-
ngx_process = NGX_PROCESS_MASTER;
-
ngx_init_signals(NULL);
-
printf("hello worker program !!\n");
-
ngx_master_process_cycle(NULL);
-
-
return 0;
-
}
阅读(5385) | 评论(0) | 转发(0) |