audi02
audi02

Reputation: 661

can't catch exception in main thread when other thread active and has try-catch

Main thread can't catch an exception (that was thrown in the main thread) while another thread with try-catch is still active. How to solve it? example:

int main()
{
  // try-catch of main thread
  try
  {
     // run a thread
     std::thread cThread([]()
     {
        // try-catch of secondary thread
        try
        {
           // makes thread works for 500 ms in order main thread will call
           // throw while thread is still active.  
           std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
        catch (...)
        {
        }
     });

     // Any call to throw BEFORE thread is finished, won't be catch.  
     // HOW TO SOLVE IT??
     throw 1;

     // wait thread finished
     cThread.join();

     // IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE 
     // CATCH.
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}

Upvotes: 1

Views: 1477

Answers (3)

audi02
audi02

Reputation: 661

Thanks to molbdnilo and quetzalcoatl. I now made the code works by using std::async instead of std::thread:

First, the problem is not related to try-catch in the thread. It was mine mistake to think it is. So here is a failure code:

int main()
{
  // try-catch of main thread
  try
  {
     // run a thread
     std::thread cThread([]()
     {
     });

     // Any call to throw BEFORE thread join won't be catch.  
     // HOW TO SOLVE IT??
     throw 1;

     // wait thread finished
     cThread.join();

     // IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE 
     // CATCH.
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}

And a code that works:

int main()
{
  std::future<void> cF;

  // try-catch of main thread
  try
  {
     // run a thread
     cF = std::async(std::launch::async, []()
     {
     });

     // You can call throw , it will be catch :)  
     throw 1;

     // wait thread finished
     if (cF.valid())
     {
        cF.get();
     }
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}

Upvotes: 0

molbdnilo
molbdnilo

Reputation: 66371

It's not so much that the exception isn't caught as it is that destroying a joinable thread terminates the process. So your program terminates before the exception handler can be executed.

If you declare the thread outside the try-catch block, the exception will be caught.
Remember that you also need to join the thread if the exception was thrown.

Upvotes: 4

quetzalcoatl
quetzalcoatl

Reputation: 33506

You've got something wrong. I mean, you've misunderstood something.

It can't be about try-catch. 'throw' and 'try-catch' are intra-thread things, they live only on the current thread, whatever it would be at the moment of throwing, main thread or the other.

Another thread cannot catch exception thrown from current thread. Exceptions does not cross threads, unless you really want it and implement it as, for example, something on current thread catches the exception and passed them to other thread and then re-throws/etc these exceptions there. You don't have any such things, so it cannot be it.

You have a join() call after the throw, and you expect that throw 1 will skip over it. That's true. However, there's also the std::thread cThread variable in the scope.

Since the thread is running, and due to throw 1 the thread has never been join()ed yet, then the expected thing to see would be program termination (see https://stackoverflow.com/a/13984169/717732), because the destructor of std::thread would detect the un-join()ed thread. That means, the std::cout << "Catched exception " << e << " in main"; should never be called. Even if the thread has somehow finished, your program should still terminate, since it does not change the fact it was not join()ed (see https://en.cppreference.com/w/cpp/thread/thread/joinable)

However, depending on library, compiler, debugger, etc, the effect you see may differ. For example, if you run it in a debugger, it may wait until all threads finish, and you'd get the effect of "waiting until inner thread finished". Hard to say.

If you actually see the "Catched exception " << e << " line running, the you've got a real problem. Either you are running something else than your current code, or your stdlib is broken. A broken stdlib might for example do a silent join() in the destructor of std::thread instead of terminating the program. Who knows. Broken lib can do many things.

Upvotes: 2

Related Questions