Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #608 (closed defect: duplicate)

Opened 1 year ago

Last modified 3 months ago

Print out exceptions in threads

Reported by: mandel Assigned to: sean
Priority: major Milestone: 1.0
Component: Core Functionality Version: 0.99 RC3 Xammy
Keywords: triage Cc:

Description

When a Thread receives an Exception, then the thread just get killed, but the Exception is not written to the console.

That's a behavior that is different from exceptions thrown from main(). It's not expected behavior and makes finding bugs harder.

Simple solution: Threads should also print out exceptions before they die.

Change History

09/04/07 12:02:42 changed by sean

  • status changed from new to assigned.

I've been debating about how to handle this. Java actually allows a default handler to be set, which is kind of a neat idea. I think I'll add printing for now and see about adding handler functionality for the next release.

09/04/07 19:43:42 changed by kris

I had a go at this over the weekend, and added an rt_exception() to dmain using the body of code in there for handling those exceptions. Then, looking at it again from Thread, it didn't seem so clear-cut anymore so I backed away :)

What did you have in mind, sean?

09/04/07 22:22:27 changed by sean

I was thinking of being able to set a callback:

void onUnhandledException( Exception e )
{
    Stdout( e ).newline;
}

Thread.exceptionHandler = &onUnhandledException;

This would allow the user to terminate the app if he wants, etc.

09/04/07 23:35:28 changed by kris

Yes, that seems like a good idea

09/04/07 23:54:02 changed by sean

Oh hold on. The current behavior for unhandled exceptions is for them to be re-thrown when Thread.join() is called. This being the case, if printing were to occur it would only happen when the thread object is disposed of if Thread.join() was never called. But because this wouldn't happen promptly when the error occurred, it could be kind of weird to do so.

I may still do something about an exception handler, but it must be considered in light of the re-throwing aspect above. Perhaps something like this:

Object onUnhandledException( Object o ) // objects can be thrown, unfortunately
{
    Stdout( e ).newline;
    return null; // exception was handled so don't rethrow on Thread.join()
}

I think the real benefit to a user-overridable handler here is that it allows the application to be forcibly terminated on an unhandled exception. I think some people would like this behavior.

09/05/07 00:49:23 changed by kris

Yeah, that's why I left it alone :)

Perhaps the default exception handler (overridable) should emit to the console using rt_exception() or something?

01/14/08 21:06:40 changed by sean

It could, but then the facility to re-throw them would seem out of place. I'd almost rather leave the default behavior as-is and let the user override to print if desired, with user handling of exceptions preventing them from being re-thrown. This seems like a "nice to have" but I don't see any pressing need for it.

05/24/08 13:17:31 changed by larsivi

  • keywords set to triage.

07/25/08 15:14:45 changed by sean

  • status changed from assigned to closed.
  • resolution set to duplicate.

Because Thread.join() will rethrow an unhandled exception I think it may be confusing if the user can override the unhandled exception code to do something else. So I would suggest simply trapping and printing the exception within the thread routine itself if desired:

class NoRethrowThread : Thread
{
    this( void delegate() dg )
    {
        isFn = false;
        this.dg = dg;
        super( &run );
    }

    this( void function() fn )
    {
        isFn = true;
        this.fn = fn;
        super( &run );
    }

    void run()
    {
        try
        {
            if( isFn ) fn();
            else       dg();
        }
        catch( Object o )
        {
            // print o.toUtf8()
        }
    }

    union
    {
        void function() fn;
        void delegate() dg;
    }

    bool isFn;
}