I have 2 threads, the main thread that is a producer, and a consumer. When the consumer throws an error, I pass it back to the main thread to throw it, but:
Once the exception is received by the main thread, I cannot rethrow it without doing consumer.join() before, otherwise the exception is not catched.
when an error from the main thread (that has nothing to do with the consumer) is thrown, it is catched only if the consumer has not been started (i.e ne thread is running).
it seems that all threads than the main one needs to be stopped to be able to catch errors. But it is weird. I won't add a "stopThread" function in all throws that are not related to the consumer.
I don't have code to show because this is a more general question and there might be some common rule that i don't know. don't hesitate if i lake informations.
Related
Suppose my main thread has started a few child threads and i have used join method so that main thread will execute after the child threads have finished its execution.
But now say child thread has thrown some exception, so in this case how would I know that child threads have thrown exception?
Maybe the following post can help
Method 1: try ... catch in child thread
Method 2: set the exception handler UncaughtExceptionHandler for the thread
Method 3: catch the exception through the get method of Future
Exception handling in Java child threads
Overview
Great question! There are a few ways to handle this implementation, each with their own benefits. Since the Java Concurrency Library is quite robust, I will be explaining the processes with Java Examples, but the concepts translate well to other languages.
Proactive
A proactive approach attempts to handle all exceptions within the child threads. Below is the run() method in a thread implementation.
public void run() {
try {
computations();
} catch (Throwable t) {
// Handle the exeception
}
}
This can be quite beneficial because threads can act more independently and allow themselves to die if they require it.
Uncaught Exception Handler
In this implementation, the ExceptionHandler's uncaughtException(Thread thread, Throwable t) is overridden and acts as the handler for the children threads in conjunciton with a ThreadFactory. Here, we allow the thread's implementation of run() to require no exception handling to work safely. The exception, if thrown will be caught by the ThreadFactory's ExceptionHandler instead. This can be beneficial because it requires exception handling to be standard between many thread implementations as well as removes the handling from the thread design.
Note - Exceptions throw from thread only execute the exception handler when executed via execute(). submit() on the other hand will return any exception as a part of the thread status.
Thread Pool Executor Handler
In this implementation, one would override the afterExecute(Runnable r, Throwable t) method for handling the Exceptions. This acts similarly to the above example except this will be used in conjunction with a ThreadPool. However, there are a few differences to note; this method should be utilized when you require thread-specific actions to recover or kill the `thread.
Future Get
In this approach, the implementation will include the use of Futures.
Future<?> myFuture = threadPool.submit(new myThreadImpl());
try {
myFuture .get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Maintain status
} catch (ExecutionException e) {
// ... Handle the exception
}
With the use of submit(), myFuture().get() will re-throw any exception from the thread if one was thrown during execution by wrapping it in an ExecutionException. This can be beneficial because it allows for exception handling to occur when attempting to access the results from the get().
In a thread I catch ThreadCanceledException, but not others, in hope to see errors, if any. However, when a thread starts and the code has an error, it produces messages
A first chance exception of type 'System.Exception' occurred in ...
The thread ... has exited with code 259 (0x103)
and gracefully quits without showing the actual exception. The error can be identified only if I run the code in UI thread.
Is there a way to get the actual exception to be reported within a thread?
You can trace those exceptions by using the TaskScheduler.UnobservedTaskException event:
TaskScheduler.UnobservedTaskException += (sender, eventArgs) =>
{
Debug.WriteLine("Unobserved exception: {0}", eventArgs.Exception);
};
Note that this event will not be triggered immediately, but after the faulty task has been collected by the garbage collector. That's because the code that created the task is the one supposed to observe the exception (for instance by calling task.Wait() or task.Result, or by awaiting it). The event will be triggered only once the runtime is certain that nobody else can observe the exception.
I'd like to be able to handle an async exception in thread A such that if another thread B calls throwTo, that call blocks until my handler in A has a chance to finish. As I understand it throwTo only blocks until the exception is "received".
I thought maybe some clever use of uninterruptibleMask might help me, but I'm stumped.
EDIT: I just noticed this:
The difference between using try and catch for recovery is that in
catch the handler is inside an implicit block (see "Asynchronous
Exceptions") which is important when catching asynchronous exceptions, ...
I thought that might be suggesting that catch would actually do what I'm looking for (I was using onException), but that doesn't seem to be the case. So as an additional question: what is meant by "the handler is inside an implicit block" here?
I am trying to listen to RabbitMQ queue by polling it. But somehow due to network issues if once connection to queue is lost then thread silently dies off and connection and everything is closed. But this is a background task and we wont know untill queue really grows huge and start send out notification.
Can some one please help me with graceful shutdown of thread (which I guess I am already doing by dealing carefully with exception in catch clause). But I don't know how to re-start a stopped thread.
Is there a way through which I can restart a new instance of stopped thread.
PS: I am instantiating the thread using #postconstruct and calling init thread soon after container loads all beans.
This sounds to me that you are not doing proper exception handling. You say "thread silently dies off" but that doesn't happen in Java. I would audit your exceptions and watch for the following problems:
Watch out for throws Exception on a method. This hides all sorts of evils. A method should usually enumerate the exceptions that it throws.
If an Exception throws too many different types of exceptions then that is a signal that it is too large. Consider splitting it into multiple smaller methods. Or handle the specific exceptions inside of the method and throw one exception out.
Try to have small try/catch blocks which catch a single exception if possible. Don't inclose huge blocks of code with try { ... } catch (Exception e) { ... }. That, again, hides evils.
If you catch an exception, make sure you aren't just blindly continuing. If this is a background thread then maybe it should exit or restart the socket or...
Make sure you are properly reporting all exceptions. Every catch block should do something with the exception. e.printStackTrace() may work but providing more information about the problem is usually in order.
But I don't know how to re-start a stopped thread.
You do not re-start a stopped thread, you start another one. If the thread should not be shutting down at all then it needs to re-open a socket or maybe re-start its RabbitMQ connection. Again, it's about proper exception handling. I don't know RabbitMQ but something like the following pseudo code might help:
public void run() {
while (!shutdown) {
Connection conn = null;
try {
conn = rabbitMq.start();
processQueue(conn);
} catch (IOException e) {
// TODO: log the exception here
} finally {
// make sure we close the connection
if (conn != null) { conn.close(); }
}
try {
// we sleep here to not spin if the RabbitMQ host goes down
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
// bail if someone interrupts us
return;
}
}
Best of luck.
If you are properly ("gracefully") handling the exception then your connection will be retrieved by thread .. just put it in while true loop and keep listening to queue ..Once network connection (and eventually queue connection) will be alive then your thread will get the connection.
I have a main application with a global exception handler installed. Now, for some specific exceptions being raised within another thread I want the global exception handler to be invoked. But it does only handle exceptions from the main thread. I also tried the following from within the thread but it does not work either:
RunInMainThread (procedure
begin
raise EExceptionFromWithinThread.Create;
end);
where RunInMainThread just executes the anonymous method given as a parameter in the context of the main thread.
Why doesn't this work? What's the proper way to handle such a situation?
How about this: send a message to the main thread which exception should be raised.
I handled the exception in the thread, saving the message as a common string variable. When the status of the thread changed, I checked the variable in the main thread. Makes for very readable code.
I do this in my framework if you are interested (http://www.csinnovations.com/framework_overview.htm).