偶然在翻看fcgi库源码时,发现fcgi库自身支持绑定并监听套接字。因此自己试了下,确实可以使用。
环境:
1. CentOS 6.3 32bit
2. Nginx 1.7.5
3. Fcgi-2.4.1
安装过程就不说了,看README和INSTALL文件,或者configure –h
首先处理2个信号SIGCHLD和SIGTERM
signal(SIGCHLD, sig_handler);
signal(SIGTERM, sig_handler);
然后创建子进程处理逻辑,父进程则监听子进程结束的信号
pid = fork();
switch(pid)
{
case 0:
run_child();
break;
case -1:
syslog(LOG_INFO, "fork error");
return -1;
default:
wait(NULL);
break;
}
信号处理函数
void sig_handler(int sig_no)
{
switch(sig_no)
{
// 如果子进程结束则马上重启
case SIGCHLD:
pid = fork();
switch(pid)
{
case 0:
run_child();
break;
case -1:
exit(-1);
default:
wait(NULL);
break;
}
break;
// 如果父进程收到SIGTERM信号,则结束父子进程
case SIGTERM:
if(pid > 0)
kill(pid, SIGTERM);
exit(0);
default:
break;
}
}
对于监听套接字,主要是2个函数
socketId = FCGX_OpenSocket("/var/run/fcgi.sock", 1024) // unix domain
socketId = FCGX_OpenSocket(":9000", 1024) // tcp/ip
FCGX_InitRequest(&request, socketId, 0)
其实还是比较简单,下面是完整代码
#include "fcgi_config.h"
#include
#include
#include
#include
#include
#include
#include
#include "fcgiapp.h"
#define THREAD_COUNT 20
#define UNIX_SOCK "/var/run/fcgi.sock"
static int counts[THREAD_COUNT];
int socketId;
pid_t pid;
void run_child();
static void *doit(void *a)
{
int rc, i, thread_id = (int)a;
pid_t pid = getpid();
FCGX_Request request;
char *server_name;
if(FCGX_InitRequest(&request, socketId, 0) != 0)
{
return NULL;
}
for (;;)
{
static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Some platforms require accept() serialization, some don't.. */
pthread_mutex_lock(&accept_mutex);
rc = FCGX_Accept_r(&request);
pthread_mutex_unlock(&accept_mutex);
if (rc < 0)
break;
server_name = FCGX_GetParam("SERVER_NAME", request.envp);
FCGX_FPrintF(request.out,
"Content-type: text/html\r\n"
"\r\n"
"FastCGI Hello! (multi-threaded C, fcgiapp library) "
"FastCGI Hello! (multi-threaded C, fcgiapp library)
"
"Thread %d, Process %ld"
"Request counts for %d threads running on host %s
",
thread_id, pid, THREAD_COUNT, server_name ? server_name : "?");
pthread_mutex_lock(&counts_mutex);
++counts[thread_id];
for (i = 0; i < THREAD_COUNT; i++)
FCGX_FPrintF(request.out, "%5d " , counts[i]);
pthread_mutex_unlock(&counts_mutex);
FCGX_Finish_r(&request);
}
return NULL;
}
void sig_handler(int sig_no)
{
switch(sig_no)
{
case SIGCHLD:
syslog(LOG_INFO, "child exit");
pid = fork();
switch(pid)
{
case 0:
run_child();
break;
case -1:
syslog(LOG_INFO, "fork error");
exit(-1);
default:
wait(NULL);
break;
}
break;
case SIGTERM:
if(pid > 0)
{
kill(pid, SIGTERM);
}
syslog(LOG_INFO, "program terminating..\n");
closelog();
exit(0);
default:
break;
}
}
void run_child()
{
int i;
pthread_t id[THREAD_COUNT];
syslog(LOG_INFO, "child staring..\n");
FCGX_Init();
umask(0);
//if( (socketId = FCGX_OpenSocket(UNIX_SOCK, 1024)) < 0)
if( (socketId = FCGX_OpenSocket(":9000", 1024)) < 0)
{
syslog(LOG_INFO, "FCGX_OpenSocket failed\n");
exit(1);
}
for (i = 1; i < THREAD_COUNT; i++)
{
pthread_create(&id[i], NULL, doit, (void*)i);
}
doit(0);
}
int main(void)
{
daemon(1, 1);
signal(SIGCHLD, sig_handler);
signal(SIGTERM, sig_handler);
openlog("fcgi_threads", LOG_PID, LOG_USER);
syslog(LOG_INFO, "program starting..");
pid = fork();
switch(pid)
{
case 0:
run_child();
break;
case -1:
syslog(LOG_INFO, "fork error");
return -1;
default:
wait(NULL);
break;
}
return 0;
}