提问人:idiot one 提问时间:11/3/2023 更新时间:11/3/2023 访问量:31
使用 sigaction(SIGCHLD, &sigchld_action, NULL) 时的父进程退出
Parent Process exit when using sigaction(SIGCHLD, &sigchld_action, NULL)
问:
我正在学习 sigaction SIGCHLD 如何处理僵尸进程。 我的期望是子进程休眠 5-30 秒(基于随机数),父进程休眠 30 秒。
但奇怪的是,父进程在子进程退出之前退出。为什么?
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
sig_atomic_t child_exit_status;
void clean_up_child_process(int signal_number){
int status;
wait(&status);
child_exit_status = status;
}
int main(){
struct sigaction sigchld_action;
int random_number;
pid_t child_pid;
memset(&sigchld_action, 0, sizeof(sigchld_action));
sigchld_action.sa_handler = &clean_up_child_process;
sigaction(SIGCHLD, &sigchld_action, NULL);
for (int i = 0; i < 5; i++) {
child_pid = fork();
if (child_pid < 0) {
perror("fork");
exit(1);
}
if (child_pid == 0) {
// Child process
printf("Child %d created\n", i);
srand(time(NULL)^getpid());
random_number = (rand()%25)+5;;
printf("random number is %d\n", random_number);
sleep(random_number); // Simulate some work in the child
exit(0);
}
}
sleep(30);
return 0;
}
答:
1赞
Jonathan Leffler
11/3/2023
#1
您的问题是,通话在被打断时会返回,告诉您还剩下多少秒的睡眠时间。如果结果为 0,则表示未中断。否则,还剩下一些时间。当第一个子项在 10 秒时退出时,调用返回 20,您应该循环:sleep()
sleep()
unsigned naptime = 30;
unsigned napleft;
while ((napleft = sleep(naptime)) != 0)
{
printf("%5d: woke up with %u seconds left - leave me in peace!\n",
getpid(), napleft);
naptime = napleft;
}
printf("%5d: I'm awake again\n", getpid());
int status;
int corpse;
while ((corpse = wait(&status)) >= 0)
{
print("Parent %5d: child %5d exited with status 0x%.4X\n",
getpid(), corpse, status);
}
请注意,在多进程代码中,通过包含 PID 来识别哪个进程正在打印每条消息通常很有帮助。不要试图通过保存值来优化呼叫,这很容易导致误导性诊断,这比没有诊断更糟糕。(无论如何,是最快的系统调用之一;开销是无法衡量的。getpid()
getpid()
在评论中,我提到了 .我认为这无济于事,因为无法重新启动。SA_RESTART
sigaction()
sleep()
考虑如何报告退出的子项的退出状态,但要注意如何避免在信号处理程序中使用 printf()
?。考虑是否在子代码中替换为 ,以便可以从退出状态中判断是哪个子代码报告了它。exit(0)
exit(i + 10)
评论
int status; int corpse; while ((corpse = wait(&status)) >= 0) print("Parent %5d: child %5d exited with status 0x%.4X\n", getpid(), corpse, status);
SA_RESTART