0

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())

Ed Rowlett-Barbu
  • 1,611
  • 10
  • 27
  • I'd be surprised if there was a portable way to kill a process launched using `system()`. – NPE Sep 29 '14 at 06:48
  • I do not wish to kill the process. Just the thread that launched it.It's ok for me to do so since the process rarely halts. So I'd have a few processes stuck at the end of the day but that's no problem. – Ed Rowlett-Barbu Sep 29 '14 at 06:49
  • 1
    You did explicitly ask for a way to terminate the child process, in your first paragraph. As for killing the thread, what thread library are you using? The C++11 `std::thread`, or something else? – Useless Sep 29 '14 at 06:57
  • 1
    That's something you can't even do reliably with any platform specific threading library! Killing threads always ends badly. But there's not really any need to do so, just use a timed wait on the process - if it times out you know it didn't finish in time. – Voo Sep 29 '14 at 06:58
  • http://stackoverflow.com/questions/12207684/how-do-i-terminate-a-thread-in-c11 – T.C. Sep 29 '14 at 07:00
  • @Useless I'm using the `std::thread` library, yes. – Ed Rowlett-Barbu Sep 29 '14 at 07:01
  • @Voo can you tell me more about the timed wait solution? I don't understand what you're referring to. – Ed Rowlett-Barbu Sep 29 '14 at 07:01
  • @T.C the thread you link doesn't provide a solution for non-cooperatively killing a thread. – Ed Rowlett-Barbu Sep 29 '14 at 07:03
  • @UselessI have update my question with a "P.S" – Ed Rowlett-Barbu Sep 29 '14 at 07:09
  • It's telling you that it's impossible in standard C++. – T.C. Sep 29 '14 at 07:09
  • `I simply do not wish to wait for that thread anymore. How do I achieve that?` Just don't do anything. – Alex F Sep 29 '14 at 07:15

2 Answers2

1

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().

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 1
    side note to the answer: If we want to relatively-safely **terminate** a job that went wild and i.e. fallen into infinite loop or infinite wait, and does not respond to any polite asking, the only option is to have that job executed **in separate process**. That separate process we will be able to suspend, resume, give priority, just like a thread, and also - we will be able to **kill** without any risks for your master process. Of course, IPC is much slower than talking to a thread.. much slower. – quetzalcoatl Sep 29 '14 at 07:55
  • @quetzalcoatl true but the OP is interested in a standard C++ solution. – n. m. could be an AI Sep 29 '14 at 07:57
  • Yes, that's why that's just a comment, the OP asked for termination of jobs/threads, you've said it's a big no-no, I dropped a note how that can be done safely.. maybe it will help someone else even if OP ignores that. – quetzalcoatl Sep 29 '14 at 07:58
  • thanks for the info guys. I did take using another process into consideration, however I'd rather go with threads if possible. – Ed Rowlett-Barbu Oct 05 '14 at 05:46
0

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...

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156