简体   繁体   English

当父调用exit(0)时子进程卡在fork()中

[英]child process stuck in fork() when parent calls exit(0)

Background:背景:

My program test.c is creating a daemon process.我的程序test.c正在创建一个守护进程。

Code snippet from test.c which creates a daemon process.来自 test.c 的代码片段,它创建了一个守护进程。

sigset_t set;
pid_t   pid;
if ((pid = fork()) < 0)
{
    printf("Did not create the daemon process\n");
    exit(1);
}
else if (pid != 0)
{
    exit(0);
}
setsid();
chdir("/");
closefiles();
...

I use a rc script to start my program test.c.我使用 rc 脚本来启动我的程序 test.c。

Problem:问题:

On rare occasions I see that the script hangs and the test.c daemon is hung in the fork() system call.在极少数情况下,我看到脚本挂起,并且 test.c 守护进程挂在 fork() 系统调用中。

Backtrace of the process seen in gdb.在 gdb 中看到的过程的回溯。

(gdb) bt
#0  0x00007f6743dd5859 in __unregister_atfork () from /lib64/libc.so.6
#1  0x00007f6744f215f3 in __do_global_dtors_aux () from <an internal library>
#2  0x00007ffd358e29b0 in ?? ()
#3  0x00007f674566786a in _dl_fini () from /lib64/ld-linux-x86-64.so.2
Backtrace stopped: frame did not save the PC

I think this could be due to race condition.我认为这可能是由于比赛条件。 I could understand that the parent process exited even before the fork() system call in child completed execution, this has caused some sort of deadlock.我可以理解父进程甚至在子进程中的 fork() 系统调用完成执行之前就退出了,这导致了某种死锁。 It seems like this happens in a very small time window, because adding a printf() statement before exit(0) lead to successful execution of the script and the daemon process.似乎这发生在很短的时间内 window,因为在 exit(0) 之前添加 printf() 语句会导致脚本和守护进程成功执行。

This code works!此代码有效!

sigset_t set;
pid_t   pid;
if ((pid = fork()) < 0)
{
    printf("Did not create the daemon process\n");
    exit(1);
}
else if (pid != 0)
{
    printf("Parent process about to exit\n");
    exit(0);
}
printf("Started child process\n");
setsid();
chdir("/");
...

What I want to understand:我想了解的:

  1. How do I debug this problem to understand why exit() caused the fork() to hang.如何调试此问题以了解 exit() 导致 fork() 挂起的原因。
  2. What would be an ideal way to solve this?解决这个问题的理想方法是什么? I was thinking I could signal the parent after successful execution of fork(), only after it has received the signal the parent should exit.我在想我可以在成功执行 fork() 后向父级发出信号,只有在它收到父级应该退出的信号之后。

I think this problem is related to atfork handlers .我认为这个问题与atfork 处理程序有关。

From your GDB backtrace, the parent process is doing cleanup works before process termination, which called __unregister_atfork() .从您的 GDB 回溯中,父进程正在进程终止之前进行清理工作,这称为__unregister_atfork()

For debug purpose, you can attach to the child process and find out what it waits for.出于调试目的,您可以附加到子进程并找出它在等待什么。 I expect the child process is running atfork handlers.我希望子进程正在运行 atfork 处理程序。 If you change exit() to _exit() to avoid parent cleanup, or change fork() to raw syscall to avoid running atfork handlers, this problem should disappear.如果您将exit()更改为_exit()以避免父清理,或将fork()更改为原始系统调用以避免运行 atfork 处理程序,则此问题应该会消失。

You may use double forks and terminate parent process after child initialization done, according to SysV Daemon requirements.根据SysV 守护进程的要求,您可以在子初始化完成后使用双叉并终止父进程。

If you are sure that your program doesn't misuse pthread_atfork() , you can try newer compiler and glibc.如果您确定您的程序没有滥用pthread_atfork() ,您可以尝试更新的编译器和 glibc。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM