gpt4 book ai didi

C++ 守护进程不会接收 SIGCHLD 信号

转载 作者:太空宇宙 更新时间:2023-11-04 04:14:00 24 4
gpt4 key购买 nike

我正在编写能够恢复工作进程的守护进程CentOS 版本 5.7(最终版)

这里是代码示例:

#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 信号,但我也想在父进程中接收另一个信号。

有什么想法吗?

最佳答案

我猜,信号处理程序在第一次 fork 之前没有安装?

关于C++ 守护进程不会接收 SIGCHLD 信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17769601/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com