Reputation: 15
Background:
My program test.c is creating a daemon process.
Code snippet from test.c which creates a daemon process.
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.
Problem:
On rare occasions I see that the script hangs and the test.c daemon is hung in the fork() system call.
Backtrace of the process seen in 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. 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.
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:
Upvotes: 1
Views: 777
Reputation: 66
I think this problem is related to atfork handlers.
From your GDB backtrace, the parent process is doing cleanup works before process termination, which called __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.
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.
You may use double forks and terminate parent process after child initialization done, according to SysV Daemon requirements.
If you are sure that your program doesn't misuse pthread_atfork()
, you can try newer compiler and glibc.
Upvotes: 2