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?
EDIT:
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()
Related
In a multithreaded Linux/C++-program, I want to use fork() with a signal handler for SIGCHLD.
In the child process I use open() to create two new file descriptors, sendfile() and close(), then the child exits.
I planned to use fork() to implement the following requirements:
The threads in the parent process shall be able to
detect the normal termination of the child process, and in that case shall be able to create another fork() doing the open()/sendfile()/close() for a range of files
kill the sendfile()-child process in case of a specific event and detect the intentional termination to clean up
For requirement 1 I could just wait for the result of sendfile().
Requirement 2 is why I think I need to use fork() in the first place.
After reading the following posts
Threads and fork(). How can I deal with that?
fork in multi-threaded program
I think that my solution might not be a good one.
My questions are:
Is there any other solution to implement requirement 2 ?
Or how can I make sure that the library calls open(), close() and sendfile() will be okay?
Update:
The program will run on a Busybox Linux / ARM
I've assumed that I should use sendfile() for having the most efficient file transfer due to several posts I've read regarding this topic.
A safe way to implement my requirement could be using fork() and exec*() with cp, with the disadvantage that the file transfer might be less efficient
Update 2:
it's sufficient to fork() once in case of a specific event (instead of once per file) since I switched to exec*() with rsync in the child process. However the program needs invoke that rsync always in case of a specific event.
You can use threads, but forcefully terminating threads typically leads to memory leaks and other problems.
My linux experience is somewhat limited, but I would probably try to fork the program early, before it gets multithreaded. Now that you have two instances, the single threaded instance can be safely used to manage the starting and stopping of additional instances.
Using only standard C++ (no platform specific API), I would like to launch an external application that may complete immediately or timeout. If the application halts, my app has a timeout after which it simply terminates the app and relaunches it.
Now, down to the nitty gritty, I tried launching two threads:
first thread launches the app and waits for it to terminate
second thread waits for a few seconds and checks if the first thread terminated. If it did not, then it considers it as stalled.
Question is, how do I terminate the first thread from the second? The way I'm launching the app is using the system() function. It's synchronous so there isn't any way for me to check from that thread if I wish for termination. It has to be forced somehow through an exception, externally.
How is this done properly?7
P.S.: if this is not possible, and I suspect it isn't, then I simply do not wish to wait for that thread anymore. It can simply remain stalled in the background. How do I achieve that? (currently, I'm waiting for that thread with a join())
You cannot forcefully terminate another thread. You can only politely ask it to exit. This holds in C++ and POSIX thread models. Windows has TerminateThread, but it's so dangerous it's practically unusable. POSIX has pthread_cancel. That's cooperative termination which could fit your bill, but there's no standard C++ equivalent.
Even if you terminate a thread somehow, it does nothing to any program it might have launched via system.
To let a thread go free with no obligation to join, use thread::detach().
To answer your question about killing a thread, POSIX offers two functions:
pthread_cancel();
This will stop the thread at a cancellation point.
The other is:
pthread_kill();
This function will send a signal to the thread. Contrary to the cancellation pointer concept, this one can happen at any point in the thread. In other words, if the thread has a mutex locked at that time, you're going to lose that lock... (unless you cleanly handle the signal in that thread).
However, what you are describing is a system() call which you make in a separate thread so that way you are not blocked. I don't think that either of these functions are going to help you because there is another process running, not just a simple thread. What you need is to stop that other process.
In your case, what you need to do is find out the pid of the child (or children) and send a signal to that child process (or all children and grandchildren, etc). In that case, you use the kill() function like so:
kill(child_pid, SIGINT);
Once the child died and cleaned up, the system() call will return and your thread is ready to be joined. So in order, you do:
...
child_pid = find_child_pid(); // Note: there is no such function, you have to write it or use a library which offers such
kill(child_pid, SIGNINT);
pthread_join(thread_id);
If that child process can create children and you want them out of the picture too (like in a shell when you hit Ctrl-C) then you need to find about all the children of your child, and their children, etc. You do so by looking at the PPID (Parent PID) of each process to see if it matches one of the children. That info is available in the /proc/<pid>/stat or /proc/<pid>/status. (the first file is probably best because it's just one line, however, it is tricky to go past the process name since it can include parenthesis... so you have to make sure to search the ')' from the end of the line (otherwise you could find a ) from the program name). Once you've got that, skip the state and there is the PPID. (So ) S <ppid>).
Repeat the search until all the parent/child are found and then start sending a SIGINT or SIGTERM or SIGKILL to each on of them.
As mentioned in the other answer, you can use pthread_detach() to quit your software and leave that other thread behind. This is probably much less desirable if you want that other process to end before your main process ends. It very much depends on what you are trying to accomplish, too.
Another, probably much more complicated way, is to use fork() + execve(). That means you have to re-implement your own system() call, but the advantage is that you do not need a thread and you get the pid of the child for free (i.e. thus you can kill it without searching for the child pid). If the function you need to run is not dynamically defined with a varying set of command line arguments, it's not too complicated. If you need to change stdin, stdout, stderr, and the arguments depend on all sorts of things, it becomes much more involved...
I've been trying to launch and close an external program at certain point during my code, and was relying on system() calls to accomplish that. However, here it was suggested that I use execlp and a separate std::thread entirely, in order to suppress console outputs.
The problem is, both of these solutions imply waiting for the program to close, which I want to avoid, as I need to communicate with that program (right now through UNIX sockets). Is there any way to use either execlp or std::thread to lauch a program in background, as I do with system([program]&)?
actually you can use threads :) but with care...
the simplest way to do fork before spawning any thread in parent/all process/es. then, after fork you may start any needed threads (anywhere you want: in parent as well as in child process).
doing fork there is no threads started automatically in a child process, but I suppose you don't need them... child usually do some preparations and exec required process, so you don't need to respawn any threads in it. (anyway if you want, you can do it!). then, you have to watch your child via waitpid and wait for it's death.
PS: also read man pthread_atfork if you really need some threads in a child.
Based on this SO post, and this example, I expect that, when I use fork(), will allow me executing system/execvp in non-blocking manner. However, when I try to issue a long-running child process in a fork block in the above mentioned example code, the control does not return to parent block, till the child has finished.
Can you tell a method, how I should design the code to allow non-blocking calls to system, in C/C++ code. Also, I plan to write a program, where more than one chidren are forked from a same parent. How can I get the pid of the children?
Thanks for your kind help.
fork will immediately return to both the child and parent. However, that example (test3.c) calls wait4, which like it sounds, waits for another process to do something (in this case exit).
Mentioned sample code waits for child to return after spawning - that's why it blocks.
To get the pid of child process, use return value of fork().
fork() is single system code which returns two different values - pid of child to parent process and 0 to child process. This is why you can distinguish code blocks in your program which should be executed by parent and children.
Refer to man fork(2).
Another thing you probably should pay attention to concerning fork() and wait() is that after child process exits kernel still holds some information about it (e.g. exit status) which should be consumed somehow. Otherwise such process will become 'zombie' (Z in ps output). This is work done with wait*() calls. Besides, after child exits its parent is notified by kernel with SIGCHLD. If you don't want to process children return values, you can notify system that you're going to ignore SIGCHLD with signal(), sigaction(), etc. In this case that additional data is automatically reaped off. Such behavior may be default on your system but it is still adviseable that you state such behavior explicitly to improve portability of your program.
In C++ using pthreads, what happens to your other threads if one of your threads calls fork?
It appears that the threads do not follow. In my case, I am trying to create a daemon and I use fork() with the parent exiting to deamonize it. However, in a new path through the code, I create some threads before the fork and some after. Is there an easy way to change ownership of the threads over to the new forked process rather than moving all my thread creation after the fork?
Nothing. Only the thread calling fork() gets duplicate. The child process has to start any new threads. The parents threads are left alone.
In POSIX when a multithreaded process forks, the child process looks exactly like a copy of the parent, but in which all the threads stopped dead in their tracks and disappeared.
This is very bad if the threads are holding locks.
For this reason, there is a crude mechanism called pthread_atfork in which you can register handlers for this situation.
Any properly written program module (and especially reusable middleware) which uses mutexes must call pthread_atfork to register some handlers, so that it does not misbehave if the process happens to call fork.
Besides mutex locks, threads could have other resources, such as thread-specific data squirreled away with pthread_setspecific which is only accessible to the thread (and the thread is responsible for cleaning it up via a destructor).
In the child process, no such destructor runs. The address space is copied, but the thread and its thread specific value is not there, so the memory is leaked in the child. This can and should be handled with pthread_atfork handlers also.
Quoting from http://thorstenball.com/blog/2014/10/13/why-threads-cant-fork/
If we call fork(2) in a multi-threaded environment the thread doing the call is now the main-thread in the new process and all the other threads, which ran in the parent process, are dead. And everything they did was left exactly as it was just before the call to fork(2).
So we should think twice before using them
It's usually very bad to fork a thread. The forked process is supposed to be a complete copy of the parent, except with threads it isn't. There is a function pthread_atfork() which helps sometimes. If you must fork a thread, it is best if you call exec() immediately after the fork().
I suggest you read the caveats from the POSIX developers in the documentation of fork() and pthread_atfork() (See http://pubs.opengroup.org/onlinepubs/007904975/functions/fork.html and http://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_atfork.html ).
From the fork() documentation:
The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined.
Nothing, unless one happens to be preempted by the thread running the new process.