I am working on a game, so at one point I had to use fork(), the main thread runs opengl graphics, and the child thread runs the game logic.
Now I have a problem. At some point, the user may press the 'Exit' button inside the game, which is handled by the secondary thread. Also, at some point the user may click the X button to exit the game which is handled by the main (glut) thread. So here is my question: how can I kill the other running thread, and exit?
Right now, if I close the window, the second thread keeps running, and if the second thread finishes, the first one keeps running.
Handling the 'X' button could be done using the atexit function, but I haven't found a (safe) way of killing glutMainLoop().
If you are actually calling fork() (instead of starting a new thread) then you are actually creating another running process. When fork() is called, it returns a process-id to the parent process. That can be passed to kill() to kill the process. Under linux this looks like:
#include <signal.h>
pid_t pid = fork();
if (pid == 0) {
// you are in the child process
} else if (pid > 0) {
// you are in the parent process
...
// send a termination signal
kill(pid, SIGTERM);
} else {
// fork had an error which should be logged...
}
You need to choose what signal to send the process. SIGKILL (9) kills it hard for example.
Please be precise about thread and process as they describe different subjects.
Since you use fork() you are actually dealing with processes. I recommend that you use threads instead, since it is much more memory efficient (since the program needs to be in memory only one time) and easier to handle. Of course you have to deal with critical sections yourself.
Here is a good example for working with threads.
If you insist on using processes and fork() you can still send signals and implement specific signal handlers. I'd also read some articles about IPC (Inter Process Communication) like http://tldp.org/LDP/lpg/node7.html.
Related
I'm writing a shell in cpp and I was hoping to get some advice. I have a command that will do an exec in the background, and I'm trying to keep track of which background processes are still running. I thought maybe I could keep track of the PID and do a string find on /proc/, but it seems to stay longer than it should. I'm testing it by using the sleep command, but it seems to always linger around wherever I look long after it should've finished. I'm probably just not doing the right thing to see if it is still running though.
Thanks in advance for any help.
Assuming you are spawning off the child process via fork() or forkpty(), one reasonably good way to track the child process's condition is to have the parent process create a connected-socket-pair (e.g. via socketpair()) before forking, and have the child process call dup2() to make one end of that socket-pair its stdin/stdout/stderr file descriptor, e.g.:
// Note: error-checking has been removed for clarity
int temp[2];
(void) socketpair(AF_UNIX, SOCK_STREAM, 0, temp);
pid_t pid = fork();
if (pid == 0)
{
// We are the child process!
(void) dup2(temp[1], STDIN_FILENO);
(void) dup2(temp[1], STDOUT_FILENO);
(void) dup2(temp[1], STDERR_FILENO);
// call exec() here...
}
The benefit of this is that now the parent process has a file descriptor (temp[0]) that is connected to the stdin, stdout, and stderr of the child process, and the parent process can select() on that descriptor to find out whenever the child process has written text to its stderr or stdout streams, and can then read() on that file descriptor to find out what the child process wrote (useful if you want to then display that text to the user, or if not you can just throw the read text away), and most importantly, it will know when the child process has closed its stderr and stdout streams, because then the parent process's next call to read() on that file descriptor will indicate 0 aka EOF.
Since the OS will automatically close the child process's streams whenever it exits for any reason (including crashing), this is a pretty reliable way to get notified that the child process has gone away.
The only potential gotcha is that the child process could (for whatever reason) manually call close(STDOUT_FILENO) and close(STDERR_FILENO), and yet still remain running; in that case the parent process would see the socket-pair connection closing as usual, and wrongly think the child process had gone away when in fact it hadn't. Fortunately it's pretty rare for a program to do that, so unless you need to be super-robust you can probably ignore that corner case.
On a POSIX-like system, after you create any child processes using fork, you should clean up those child processes by calling wait or waitpid from the parent process. The name "wait" is used because the functions are most commonly used when the parent has nothing to do until a child exits or is killed, but waitpid can also be used (by passing WNOHANG) to check on whether a child process is finished without making the parent process wait.
Note that at least on Linux, when a child process has exited or been killed but the parent process has not "waited" for the child, the kernel keeps some information about the child process in memory, as a "zombie process". This is done so that a later "wait" can correctly fetch the information about the child's exit code or fatal signal. These zombie processes do have entries in /proc, which may be why you see a child "stay longer than it should", if that's how you were checking.
In my process I need to start/restart another process.
Currently I use a thread with a tiny stack size and the following code:
void startAndMonitorA()
{
while(true)
{
system("myProcess");
LOG("myProcess crashed");
usleep(1000 * 1000);
}
}
I feel like that's not best practice. I have no idea about the resources the std::system() call is blocking or wasting. I'm on an embedded Linux - so in general I try to care about resources.
One problematic piece is restarting immediately: if the child process fails to start that is going to cause 100% CPU usage. It may be a transient error in the child process (e.g. cannot connect to a server). It may be a good idea to add a least one second pause before trying to restart.
What system call does on Linux is:
Sets up signals SIGINT and SIGQUIT to be ignored.
Blocks signal SIGCHLD.
fork()
Child process calls exec() shell, passing the command line to the shell.
Parent process calls waitpid() that blocks the thread till the child process terminates.
Parent process restores its signal dispositions.
If you were to re-implement the functionality of system you would probably omit step 5 (along with steps 1, 2 and 6) to avoid blocking the thread and rely on SIGCHLD to get notified when the child process has terminated and needs to be restarted.
In other words, the bare minimum would be to set up a signal handler for SIGCHLD and call fork and exec.
The code as shown would be adequate for most circumstances. If you really care about resource usage, you should be aware that you are starting (and keeping around) a thread for each process you are monitoring. If your program has an event loop anyway, that kind of thing can be avoided at the cost of some additional effort (and an increase in complexity).
Implementing this would entail the following:
Instead of calling system(), use fork() and exec() to start the external program. Store its PID in a global table.
Set a SIGCHLD handler that notifies the event loop of the exit of a child, e.g. by writing a byte to a pipe monitored by the event loop.
When a child exits, run waitpid with the WNOHANG flag in a loop that runs for as long as there are children to reap. waitpid() will return the PID of the child that exited, so that you know to remove its PID from the table, and to schedule a timeout that restarts it.
In Linux, when a signal is sent to a process/thread (for whatever reason), is the signal handler (assuming there is one, and the signal isn't blocked) called immediately?
I mean, I'm pretty sure that in the process/thread that handles the signal it will be called immediately, but I mean with respect to other processes/threads.
And if the handler is called immediately, will it also make the corresponding process/thread active (so that its normal execution continues immediatly)?
EDIT
As my original question seems to have been misunderstood, I'll try to explain again with an example.
Lets say in my computer I have a single CPU, and 2 processes running, process 'A' and process 'B'. And assume none of them is blocking in a system call (like sleep). Normally, I guess, the OS will switch between executing process 'A' and process 'B', after small periods of time (e.g. execute process 'A' for 100ms, then process 'B' for 100ms, then process A again for 100ms, etc.). Let's say process 'A' is now the active process (i.e. it's the one now occupying the CPU). Say now that process 'A' sends a signal to process 'B' (or, alternately, the OS sends this signal to process 'B', for whatever reason). Process 'B' has registered an handler for that signal, and is not blocking it. So the question is, will the OS now immediately stop executing process 'A' and switch to executing the signal handler of process 'B'? And if the answer is yes, will it afterwards immediately continue executing process 'B' (The normal code, not the signal handler), or switch back to executing process 'A', and only after some small period of time resume with executing process 'B'?
And then the same questions can be asked about threads rather than processes.
No, signals are delivered on context switch only. Upto that time all signals will be queued. Among many signals of same type, usually Only one signal is delivered to the destination. So i am comfortable to sat that more signals destroyed than delivered.
I suggest you to consult chapter regarding any unix book book. My favorite is understanding linux kernel and linux kernel development.
if you still need techincal help please comment about it
There are two cases: when the signaled process is active, and when it is blocked.
For the former case, according to http://www.tldp.org/LDP/tlk/ipc/ipc.html, the process would handle the signal when it exits from a system call. This would mean that a normal instruction like a = b+c (or its equivalent machine code) would not be interrupted because of signal. Signal handling may also be delayed in a CPU-intensive process.
However, when the process is blocked, it depends on whether the kernel function being called is interruptible (e.g., wait_event_interruptible). If it is interruptible, the process will wake up, otherwise, it will not until it leaves the uninterruptible function (due to IRQ, for instance).
Yes, the handler will be called immediately.
Suppose I have a process coded as below.
#include <stdio.h>
#include <signal.h>
void handle_signal(int signal);
volatile int i = 1;
int main( )
{
struct sigaction sa;
// Setup the sighub handler
sa.sa_handler = &handle_signal;
// Block every signal during the handler
sigfillset(&sa.sa_mask);
while(1)
{
if(i == 1)
{
printf("A");
}
}
return 0;
}
void handle_signal(int signal) {
/*
* Please note that printf et al. are NOT safe to use in signal handlers.
* Look for async safe functions.
*/
const char *signal_name;
sigset_t pending;
// Find out which signal we're handling
switch (signal) {
case SIGHUP:
signal_name = "SIGHUP";
break;
case SIGSTOP:
i = 0;
signal_name = "SIGSTOP";
break;
case SIGCONT:
signal_name = "SIGCONT";
i = 1;
break;
default:
fprintf(stderr, "Caught wrong signal: %d\n", signal);
return;
}
}
This prints A on shell all the time unless it receives SIGSTOP signal.
So, open the shell and do kill -STOP <pid of above process>
Verify that process is stopped, and then from the shell send the SIGCONT signal using kill -CONT <pid of above process>
And if the handler is called immediately, will it also make the corresponding process/thread active (so that its normal execution continues immediatly)
Your signal handler has its own context. So there is no thread which must be activated for handling your signal. But there are some issues which must be kept in mind. If your thread is waiting with some syscalls like sleep or read/write or any other blocking operation, this system call will be interrupted and the return value from that call give you the information, that your process ( not thread! ) has received a signal.This return value is EINTR. If your thread is simply running or sleeping without waiting on a system call, nothing else is happened! Simply the handler is invoked without any changes in scheduling your threads inside your process.
In my Qt C++ program I created a process as follows:
myProcess = new QProcess();
myProcess->start(programpath, arguments);
Terminating the process is handled as follows:
myProcess->terminate();
Terminating the child process with QProcess::kill(),terminate() or close() works, but I don't want to use it because it doesn't give the child process a chance to clean up before exiting.
Is there any other way to exit the process? Thanks!
The polite way would be for the parent process to politely ask the child process to go away. Then when the child process exits (of its own volition), the QProcess object will emit a finished(int, QProcess::ExitStatus) signal, and you can have a slot connected to that signal that will continue your process (e.g. by deleting the QProcess object at that time). (Or if you don't mind blocking your Qt event loop for a little while, you could just call waitForFinished() on the QProcess object after asking it to exit, and waitForFinished() won't return until the process has gone away or the timeout period has elapsed)
Of course for the above to work you need some way to ask the child process to exit. How you go about doing that will depend on what the child process is running. If you're lucky, you are in control of the child process's code, in which case you can modify it to exit in response to some action of the parent process -- for example, you could code the child process to exit when its stdin descriptor is closed, and have the parent process call closeWriteChannel() on the QProcess object to cause that to happen. Or if you're running under Linux/Unix you could send a SIGINT signal to the child process and the child process could set up a handler that would catch the signal and start an orderly shutdown. Or if you want something really stupid-quick and dirty, have the child process periodically check for the presence of a file at a well-known location (e.g. "/tmp/hey-child-process-PIDNUMBERHERE-go-away.txt" or something) and the parent process would create such a file when it wants the child to go away. Not that I'd recommend that last method as I don't think it would be very robust, except maybe as a proof of concept.
terminate actually gives the process an chance to clean up. The program being terminated just has to take that chance i.e. the system sents a SIGTERM and the application and it can ignore that and exit cleanly on its own. If this is still not nice enough then you have to implement your own way of asking the application to quit. Jeremy Friesner made some good successions. If the application code is not written by yourself you'll have to read the documentation for that program closer, maybe its documented how to do that.
I wrote a program that forks some processes with fork(). I want to kill all child- and the mother process if there is an error. If I use exit(EXIT_FAILURE) only the child process is killed.
I am thinking about a system("killall [program_name]") but there must be a better way...
Thank you all!
Lennart
Under UNIX, send SIGTERM, or SIGABRT, or SIGPIPE or sth. alike to the mother process. This signal will then be propagated to all clients automatically, if they do not explicitely block or ignore it.
Use getppid() to get the PID to send the signal to, and kill() to send the signal.
getppid() returns the process ID of
the parent of the calling process.
The kill() system call can be used to send any signal to any process group or process.
Remarks:
1. Using system is evil. Use internal functions to send signals.
2. killall would be even more evil. Consider several instances of your program running at once.
See How to make child process die after parent exits?
On Linux there's a prctl() call which is explicitly designed to send a signal to all of a process's children when the parent dies for whatever reason.
I need to check and can't do it where I am at the second, but I'm really not sure that ypnos' assertion about SIGPIPE, SIGTERM and SIGABRT being propagated to all children is correct.
However if you use kill(-ppid) (note the minus sign) then so long as the children are still in the parent process's process group then the kernel will deliver any signal to all of the children.
If your mother process is not started by the command line, it may not be the
process group leader, like as a deamon.
To ensure that your mother process is the process group leader, call setsid() during
your process initialization.
Then in your child process, if you want to cause all the processes to exit:
pgid = getpgid();
kill(pgid, 15);
You can also do tricks, like telling all your siblings to suspend:
kill(pgid, 20);
And resume:
kill(pgid, 18);
Consider suicidal approach - setting up an alarm() at the beginning of the process (both parent and child) with some positive number of seconds. If computation completes within that time and "there is no error", call alarm(0) to cancel the timer; otherwise the SIGALRM will kill the process (assuming you're not explicitly catching or ignoring it.)
Well, make a case against this instead of just down-voting :)