Another thread's exceptions?

Started by
2 comments, last by haegarr 17 years, 6 months ago
My current language project uses what could be best described as threads. I'm currently incorporating exception handling into the design, and I am wondering what is the consistent thing to do when a thread is not able to handle an exception: sure, it dies, but does it die a silent death, or rather kill the system as a whole? The language allows some (limited) manipulation of threads: the ability to cancel them, to determine if they are done, and so on. I would like to add the ability to check if the thread has encountered an unhandled exception, and have the code try to handle that exception in turn. My current approach would look like this:

  // Create a first thread, runs at T = 1
  event later = at (1.0) {
    throw Exception.invalidOperation();
  }
 
  // Create a second thread, runs at T = 2
  at (2.0) {
    try (later)
    catch (Exception.InvalidOperation ex)
      Console.print("Caught an exception!\n");
  }  
My question are: Would it make sense to add other possibilities for introspection into the reasons of failure, or is transmission of exceptions enough? Once the event has been "tried", should this purge the exceptions, or should a second try throw the same exception again? Using this approach, a thread which has been tied to an event will never stop the program. However, events are also used for other manipulations that might not include exception-handling. How can I make sure the exception will be heard at the OS level if nobody in the program checks for it? Also, a little bit unrelated : should an Assert Failure throw an exception, or do something worse altogether?
Advertisement
IMHO it is okay if the exception doesn't cross thread boundaries by itself. If the thread doesn't catch it, it reaches the thread's top, lets the thread die, and can be stored in a dedicated field of the thread's control structure. So, at points where the caller normally determines whether the thread has stopped normally, it also can check for an exception, making sure that exception catchers are around if wanted.

Configurable behaviour is also possible. E.g. parametrizing the thread with a handler means "I do handling by myself", allowing to catch, handle, and even drop an exception. Otherwise the exception will cross thread boundary until catched elsewhere in the parent thread.

However, it seems senseful to have a chance to determine what thread has been died. If exceptions don't always report the thread of occurance, and exceptions are passed through thread bondaries, then catching them at the thread's top, wrapping it by a ThreadDiedException with the belonging thread as additional parameter set, and eventually re-throwing it may also be a possibility.


Assertions are part of the design by contract (as Meyer has named it in Eiffel). Hence it is not to be expected that the part protected by the assertion can continue in a senseful manner, and hence it should fail. Throwing an exception allows at least to be catched anywhere, although it is not ever the case that assertion violations can be handles by repairing the problem. However, some applications are written with the intent to run as long as possible, and can drop the current processing step if aborted but are able to wait for the next one (e.g. applications working on chains of unrelated tasks). This is, of course, a last resort, but if the application runs at customers it is even better than to abort the whole application.

EDIT: Throwing a sub-type of exception especially for assertions allows them to pass any catcher that doesn't explicitely mention them, so they also may pass up to the top and abort the program (or thread).


Just my 2c.
Quote:However, it seems senseful to have a chance to determine what thread has been died. If exceptions don't always report the thread of occurance, and exceptions are passed through thread bondaries, then catching them at the thread's top, wrapping it by a ThreadDiedException with the belonging thread as additional parameter set, and eventually re-throwing it may also be a possibility.


The question here is: where is it re-thrown? Most of the time (actually, all of the time, but that's secondary) the parent thread will be dead and buried by the time the child thread mishandles the exception, although one or more siblings of that thread might be alive and ready to check it for failure. My question mostly relates to the case where the thread dies and nobody's there to check for it. Should the application fail, or should the failure be ignored?

Quote:Assertions are part of the design by contract (as Meyer has named it in Eiffel). Hence it is not to be expected that the part protected by the assertion can continue in a senseful manner, and hence it should fail. Throwing an exception allows at least to be catched anywhere, although it is not ever the case that assertion violations can be handles by repairing the problem. However, some applications are written with the intent to run as long as possible, and can drop the current processing step if aborted but are able to wait for the next one (e.g. applications working on chains of unrelated tasks). This is, of course, a last resort, but if the application runs at customers it is even better than to abort the whole application.


My question was related to introspection. Some languages use an "AssertFailure" exception for asserts, which allows unit testing code to check if the tested code will fail an assertion when given incorrect input, by catching the AssertFailure if it happens, or failing the test if it doesn't.

Quote:Original post by ToohrVyk
The question here is: where is it re-thrown? Most of the time (actually, all of the time, but that's secondary) the parent thread will be dead and buried by the time the child thread mishandles the exception, although one or more siblings of that thread might be alive and ready to check it for failure. My question mostly relates to the case where the thread dies and nobody's there to check for it. Should the application fail, or should the failure be ignored?

Oh, I've overseen that you may let a sibling of the child thread try to handle the exception. Well, until now I never thought of letting "neighboured" threads doing so but at most the superior threads...

Oh, and yes, then you can have concurrent exception handlers (hence your question whether the first try should remove the exception; sometimes I need longer to recognize ;). Well, if you really want to go that way, it seems me best that a try removes the exception (or blocks other tries on the same thread if real concurrency is given) and pushes it back only if (a) no suitable catcher is found during that try, or (b) a re-throw is executed manually (if that is possible). So another catcher can be enabled to handle it.

In such case it seems me not correct to let the parent thread die automatically anyway, leaving the other children as "zombies" without the parent thread being able to intervene. At what level of superior threads should such a dead stop, i.e. why should the parent thread die but the grandparent thread alive? Following this thoughts IMHO automatically means that the application doesn't die if nobody handles an exception occured in a thread, and hence total ignore of exceptions is possible. Else you have to define when the exception has passed all possible handlers, since only then an exception may terminate the parental thread. But handlers can be started lazily, too.

(Maybe I'm missing a point here, since, as said, this kind of exception handling is new to me.)

Quote:Original post by ToohrVyk
My question was related to introspection. Some languages use an "AssertFailure" exception for asserts, which allows unit testing code to check if the tested code will fail an assertion when given incorrect input, by catching the AssertFailure if it happens, or failing the test if it doesn't.

Yep, I've mentioned something similar lately with an appended EDIT paragraph in my previous reply. A special kind of exception for assertions seems me senseful.

This topic is closed to new replies.

Advertisement