我正在編寫守護進程,能夠恢復工作進程CentOS release 5.7 (Final)
。C++守護進程將不會收到SIGCHLD信號
下面是示例的代碼:
#define CHILD_NEED_WORK 1
#define CHILD_NEED_TERMINATE 2
int ReloadConfig()
{
....
return 0;
}
void DestroyWorkThread()
{...}
int InitWorkThread()
{
...
return 0;
}
int LoadConfig(char* FileName)
{
...
return 0;
}
void SetPidFile(char* Filename)
{
FILE* f;
f = fopen(Filename, "w+");
if (f)
{
fprintf(f, "%u\n", getpid());
fclose(f);
}
}
int SetFdLimit(int MaxFd)
{
struct rlimit lim;
int status;
lim.rlim_cur = MaxFd;
lim.rlim_max = MaxFd;
status = setrlimit(RLIMIT_NOFILE, &lim);
return status;
}
//Monitor process
int MonitorProc()
{
int pid;
int status;
int need_start = 1;
sigset_t sigset;
siginfo_t siginfo;
parent_pid = getpid();
sigemptyset(&sigset);
sigaddset(&sigset, SIGQUIT);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
sigaddset(&sigset, SIGCHLD);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL);
SetPidFile(PID_FILE);
for (;;)
{
if (need_start)
{
pid = fork();
}
need_start = 1;
if (pid == -1)
{
}
else if (!pid)
{
status = WorkProc();
exit(status);
}
else
{
sigwaitinfo(&sigset, &siginfo);
if (siginfo.si_signo == SIGCHLD)
{
wait(&status);
status = WEXITSTATUS(status);
if (status == CHILD_NEED_TERMINATE)
{
Write("[MONITOR] Child stopped");
break;
}
else if (status == CHILD_NEED_WORK)
{
Write("[MONITOR] Child restart");
}
}
else if (siginfo.si_signo == SIGUSR1)
{
kill(pid, SIGUSR1);
need_start = 0;
}
else if (siginfo.si_signo == 0)
{
need_start = 0;
continue;
}
else
{
Write("[MONITOR] Signal ", strsignal(siginfo.si_signo));
kill(pid, SIGTERM);
status = 0;
break;
}
}
}
Write("[MONITOR] Stop");
unlink(PID_FILE);
return status;
}
//Work process
int WorkProc()
{
struct sigaction sigact;
sigset_t sigset;
int signo;
int status;
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = signal_error_for_backtrace;
sigemptyset(&sigact.sa_mask);
sigaction(SIGFPE, &sigact, 0);
sigaction(SIGILL, &sigact, 0);
sigaction(SIGSEGV, &sigact, 0);
sigaction(SIGBUS, &sigact, 0);
sigemptyset(&sigset);
sigaddset(&sigset, SIGQUIT);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL);
SetFdLimit(FD_LIMIT);
status = InitWorkThread();
if (!status)
{
for (;;)
{
sigwait(&sigset, &signo);
if (signo == SIGUSR1)
{
status = ReloadConfig();
if (status)
{
Write("[DAEMON] Reload config failed");
}
else
{
Write("[DAEMON] Reload config OK");
}
}
else
{
break;
}
}
DestroyWorkThread();
}
else
{
Write("[DAEMON] Create work thread failed");
}
Write("[DAEMON] Stopped");
return CHILD_NEED_TERMINATE;
}
int main(int argc , char *argv[])
{
if (argc != 2)
{
printf("Usage: ./test_daemon.conf failed!\n");
return -1;
}
status = LoadConfig(argv[1]);
if (status)
{
printf("Error: Load config failed\n");
return -1;
}
if (CheckForAnotherInstance())
{
printf("Daemon is already running!\n");
return 1;
}
pid = fork();
if (pid == -1)
{
printf("Error: Start Daemon failed (%s)\n", strerror(errno));
return -1;
}
else if (!pid)
{
umask(0);
setsid();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//Monitor process startup
status = MonitorProc();
return status;
}
else
{
return 0;
}
return 0;
}
我使用兩個過程:工作過程中,其產生主要工作和監控方法,其等待來自工作過程的信號,並重新啓動它們,如果它接收到所需要的信號。當我嘗試向父進程發送一個信號 - 監視進程 - 用命令kill -s SIGCHLD,它收到這個信號。
當我嘗試終止子進程時,父進程沒有收到SIGCHLD信號 - 它等待信號,並且子進程轉換爲殭屍。
但是當我用父級進程使用實用程序strace時,所有工作正常的子進程終止成功,並且父進程接收到SIGCHLD信號。
我讀了關於函數waitpid(),它用來接收SIGCHLD信號,但我想在父進程中接收另一個信號。
任何想法?
如果你想自我守護進程,看到這個帖子瞭如何正確地做到這一點:http://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux – kfsone