double fork using vfork
HI I am writing a part of a server which should dispatch some other child processes. Because I want to wait on some of the processes, and dispatch others without waiting for completion, I use double fork for the second kind of processes (thus avoiding the zombie processes). Problem is, my server holds a lot of memory, so forking takes a long time (even the copy-on-write fork used in Linux which copies only the paging tables) I want to replace the fork() with vfork(), and it's easy for the second fork (as it only calls execve() in the child), but I couldn't find any way I can replace the first one. Does anyone know how I can do that? Thanks!
The server is a linux (RH5U4), written in C++.
Why not simply have the newly exec'd process do another fork itself? That way only a small simple process will have its page tables copied?
Of course the parent would have to do a short-duration wait() to clean up the zombie from that one, but the grandchild process could then run for as long as it wanted.
vfork() can only be used to fork and then call exec or exit. Also, vfork() will block the parent process until the child calls _exit or exec, which is almost certainly not the behavior that you want.
The reason for this is that vfork() doesn't make any copies of any of the data, including the stack, for the new process. So everything is shared, and it is very easy to accidentally change something that the parent process cannot handle. Since the data is shared without copies, the parent process cannot continue running at the same time as the child, so it must wait for the child to _exit or call exec so it is no longer using the data when the parent starts to modify it.
I think that what you really want to do is to make use of SIGCHLD and maintain a list of child processes. You can then do away with the double fork by having your main process be notified when children change state (mostly, when they die) and perform some action on them based on that. You can also keep track of of any of your child processes take longer than expected to complete (because you stored their creation time in your list) and take action if they go crazy and never complete.
Don't double fork. Handle SIGCHLD to save errno, call wait, restore errno.
I believe you can use the answer to another question I asked, for a similar reason. You can vfork() + exec() to an executable which forks again. See setuid() before calling execv() in vfork() / clone()