How to Catch an Exception from a Thread

How to catch an Exception from a thread

Use a Thread.UncaughtExceptionHandler.

Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
@Override
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();

How to catch an exception which occured in a thread?

The exact answer to my problem was given in an answer to another question (I marked mine as duplicate, but it is really that particular answer which is perfect in my context).

The code in my question modified to account for the solution:

import concurrent.futures

class Checks:

@staticmethod
def isok():
print("OK")

@staticmethod
def isko():
raise Exception("KO")

# db will keep a map of method namles in Check with the actual (executable) method
db = {}

with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
for check in [k for k in dir(Checks) if not k.startswith('_')]:
db[check] = executor.submit(getattr(Checks, check))
for future in concurrent.futures.as_completed([db[k] for k in db.keys()]):
if future.exception():
print(f"{str(future.exception())} was raised (I do not know where, somewhere)")
else:
print("success (again, I do not know where, exactly)")

# all the threads are finished at that point
print("all threads are done")

I do not know how to get the name of the future which raised the exception (I will ask a new question about that)

Catch a thread's exception in the caller thread?

The problem is that thread_obj.start() returns immediately. The child thread that you spawned executes in its own context, with its own stack. Any exception that occurs there is in the context of the child thread, and it is in its own stack. One way I can think of right now to communicate this information to the parent thread is by using some sort of message passing, so you might look into that.

Try this on for size:

import sys
import threading
import queue

class ExcThread(threading.Thread):

def __init__(self, bucket):
threading.Thread.__init__(self)
self.bucket = bucket

def run(self):
try:
raise Exception('An error occured here.')
except Exception:
self.bucket.put(sys.exc_info())

def main():
bucket = queue.Queue()
thread_obj = ExcThread(bucket)
thread_obj.start()

while True:
try:
exc = bucket.get(block=False)
except queue.Empty:
pass
else:
exc_type, exc_obj, exc_trace = exc
# deal with the exception
print exc_type, exc_obj
print exc_trace

thread_obj.join(0.1)
if thread_obj.isAlive():
continue
else:
break

if __name__ == '__main__':
main()

Catching exception from worker thread in the main thread

Firstly, you do not need to use bind with thread. Doing so just adds unnecessary copying and makes the code harder to read. I wish everyone would stop doing that.

WorkerThread::WorkerThread(){

m_thread = boost::thread(&WorkerThread::drawThread, this);

}

You can store an exception in an exception_ptr and pass that to the other thread, e.g. in std::queue<std::exception_ptr>:

void WorkerThread::drawThread()
{
while(true)
{
boost::unique_lock<boost::mutex> lock(m_mutex);
try{

///some work is done here...

}catch(std::exception &e){
m_queue.push(std::current_exception());
}
}
}

std::exception_ptr WorkerThread::last_exception()
{
boost::lock_guard<boost::mutex> lock(m_mutex);
std::exception_ptr e;
if (!m_queue.empty())
{
e = m_queue.front();
m_queue.pop();
}
return e;
}

Then in the other thread rethrow it and handle it:

if (auto ep = workerThread.last_exception())
{
// do something with exception
try
{
std::rethrow_exception(ep);
}
catch (const std::exception& e)
{
std::cerr << "Error in worker thread: " << e.what() << '\n';
}
}

If you can't use std::exception_ptr Boost has its own implementation of it, but I'm not sure what the Boost equivalent of current_exception is. You might need to wrap the exception in another object so the Boost exception propagation mechanism can store it.

You might want to use a separate mutex for the exception queue from the main work loop (and move the m_mutex lock inside the try block) depending how long m_mutex is usually locked by the worker thread.


A different approach uses C++11 futures, which handle passing exceptions between threads more conveniently. You need some way for the main thread to get a future for each unit of work the worker thread runs, which can be done with std::packaged_task:

class WorkerThread
{
public:
WorkerThread(); // start m_thread, as before

template<typename F, typename... Args>
std::future<void> post(F f, Args&&... args)
{
Task task(std::bind<void>(f, std::forward<Args>(args)...));
auto fut = task.get_future();
std::lock_guard<std::mutex> lock(m_mutex);
m_tasks.push(std::move(task));
return fut;
}

private:
void drawThread();
std::mutex m_mutex;
using Task = std::packaged_task<void()>;
std::queue<Task> m_tasks;
std::thread m_thread;
};

void WorkerThread::drawThread()
{
Task task;
while(true)
{
{
std::lock_guard<std::mutex> lock(m_mutex);
task = std::move(m_tasks.front());
m_tasks.pop();
}
task(); // run the task
}
}

When the task is run any exceptions will be caught, stored in an exception_ptr and held until the result is read through the associated future.

// other thread:

auto fut = workerThread.post(&someDrawingFunc, arg1, arg2);
...
// check future for errors
try {
fut.get();
} catch (const std::exception& e) {
// handle it
}

The producer thread could store the future objects in a queue when posting work to the consumer, and some other piece of code could check each future in the queue to see if it's ready and call get() to handle any exception.

catch exception that is thrown in different thread

In .NET 4 and above, you can use Task<T> class instead of creating new thread. Then you can get exceptions using .Exceptions property on your task object.
There are 2 ways to do it:

  1. In a separate method: // You process exception in some task's thread

    class Program
    {
    static void Main(string[] args)
    {
    Task<int> task = new Task<int>(Test);
    task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
    task.Start();
    Console.ReadLine();
    }

    static int Test()
    {
    throw new Exception();
    }

    static void ExceptionHandler(Task<int> task)
    {
    var exception = task.Exception;
    Console.WriteLine(exception);
    }
    }
  2. In the same method: // You process exception in the caller's thread

    class Program
    {
    static void Main(string[] args)
    {
    Task<int> task = new Task<int>(Test);
    task.Start();

    try
    {
    task.Wait();
    }
    catch (AggregateException ex)
    {
    Console.WriteLine(ex);
    }

    Console.ReadLine();
    }

    static int Test()
    {
    throw new Exception();
    }
    }

Note that the exception which you get is AggregateException. All real exceptions are availible through ex.InnerExceptions property.

In .NET 3.5 you can use the following code:

  1. // You process exception in the child's thread

    class Program
    {
    static void Main(string[] args)
    {
    Exception exception = null;
    Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler));
    thread.Start();

    Console.ReadLine();
    }

    private static void Handler(Exception exception)
    {
    Console.WriteLine(exception);
    }

    private static void SafeExecute(Action test, Action<Exception> handler)
    {
    try
    {
    test.Invoke();
    }
    catch (Exception ex)
    {
    Handler(ex);
    }
    }

    static void Test(int a, int b)
    {
    throw new Exception();
    }
    }
  2. Or // You process exception in the caller's thread

    class Program
    {
    static void Main(string[] args)
    {
    Exception exception = null;
    Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception));

    thread.Start();

    thread.Join();

    Console.WriteLine(exception);

    Console.ReadLine();
    }

    private static void SafeExecute(Action test, out Exception exception)
    {
    exception = null;

    try
    {
    test.Invoke();
    }
    catch (Exception ex)
    {
    exception = ex;
    }
    }

    static void Test(int a, int b)
    {
    throw new Exception();
    }
    }

handle java exception in Thread.run

If you use an ExecutorService instead of using raw threads, you can be notified of uncaught exceptions:

class MyCallable implements Callable<Void> {
@Override public Void call() throws Exception {
// Do something - you don't need to catch Exception as Callable throws it.
// ...

return null; // A return is necessary from a Callable.
}
}

Create an executor service somewhere, e.g.:

ExecutorService executor = Executors.newFixedThreadPool(1);

Then, in the code where you start the thread:

Future<?> future = executor.submit(new MyCallable());

try {
future.get(); // Blocks until the Callable completes.
} catch (ExecutionException e) {
// You reach here if an exception is thrown in the Callable -
// The exception is accessible via e.getCause().
}

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

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.



Related Topics



Leave a reply



Submit