August 08, 2012
Hi,

using std.concurrency, is it possible to print an exception if a thread throws (and the main thread is still running) ? It just terminates and prints nothing. I tried to catch it and send as a message to the main thread, but haven't succeeded so far.

-- 
mk
August 08, 2012
On 08/07/2012 06:25 PM, Martin Krejcirik wrote:
> Hi,
>
> using std.concurrency, is it possible to print an exception if a thread
> throws (and the main thread is still running) ? It just terminates and
> prints nothing. I tried to catch it and send as a message to the main
> thread, but haven't succeeded so far.

Here is an excerpt from a yet-unpublished change to my Concurrency chapter:

-----
The OwnerTerminated and LinkTerminated exceptions can be received as messages as well. The following code demonstrates this for the OwnerTerminated exception:



    bool isDone = false;

    while (!isDone) {
        receive(
            (int message)
            {
                writeln("Message: ", message);
            }
            ,

            (OwnerTerminated exc)
            {
                writeln("The owner has terminated; exiting.");
                isDone = true;
            }
        );
    }
-----

In order to receive LinkTerminated as a message, start the worker with spawnLinked() instead of spawn().

Ali

-- 
D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html

August 08, 2012
Hi Ali,

On 8.8.2012 5:36, Ali Çehreli wrote:
> The OwnerTerminated and LinkTerminated exceptions can be received as messages as well. The following code demonstrates this for the OwnerTerminated exception:

I meant how can I print the actual exception from the thread, including it's error message, stack trace etc. Consider code like this, it just ends without any error message:

import std.concurrency, std.stdio;

void main()
{
    writeln("main start");
    spawn(&child);
    for (int i=0; i<1_000_000_000; i++) {};
    writeln("main end");
}

void child()
{
    writeln("thread start");
    for (int i=0; i<100_000; i++) {};
    writeln("thread end");
    throw new Exception("exception from thread");
}

If I use spawnLinked, I know the thread ended, but still no original exception. If I change main() to terminate before child(), it actually waits until the child finishes and prints the exception, so there has to be a way.

-- 
mk
August 08, 2012
I'll have to think about it. The current approach in std.concurrency is intended to be forwards-compatible with interprocess messaging, and serializing/deserializing an arbitrary exception would be tricky. See the exception thrown by receiveOnly as an example of how I addressed the issue there.

On Aug 8, 2012, at 1:52 AM, Martin Krejcirik <mk-junk@i-line.cz> wrote:

> Hi Ali,
> 
> On 8.8.2012 5:36, Ali Çehreli wrote:
>> The OwnerTerminated and LinkTerminated exceptions can be received as messages as well. The following code demonstrates this for the OwnerTerminated exception:
> 
> I meant how can I print the actual exception from the thread, including it's error message, stack trace etc. Consider code like this, it just ends without any error message:
> 
> import std.concurrency, std.stdio;
> 
> void main()
> {
>    writeln("main start");
>    spawn(&child);
>    for (int i=0; i<1_000_000_000; i++) {};
>    writeln("main end");
> }
> 
> void child()
> {
>    writeln("thread start");
>    for (int i=0; i<100_000; i++) {};
>    writeln("thread end");
>    throw new Exception("exception from thread");
> }
> 
> If I use spawnLinked, I know the thread ended, but still no original exception. If I change main() to terminate before child(), it actually waits until the child finishes and prints the exception, so there has to be a way.
> 
> -- 
> mk
August 08, 2012
Oh, I should mention that if you use core.thread explicitly, any unhandled exception will be re-thrown in the context of whoever joins that thread.

On Aug 8, 2012, at 1:52 AM, Martin Krejcirik <mk-junk@i-line.cz> wrote:

> Hi Ali,
> 
> On 8.8.2012 5:36, Ali Çehreli wrote:
>> The OwnerTerminated and LinkTerminated exceptions can be received as messages as well. The following code demonstrates this for the OwnerTerminated exception:
> 
> I meant how can I print the actual exception from the thread, including it's error message, stack trace etc. Consider code like this, it just ends without any error message:
> 
> import std.concurrency, std.stdio;
> 
> void main()
> {
>    writeln("main start");
>    spawn(&child);
>    for (int i=0; i<1_000_000_000; i++) {};
>    writeln("main end");
> }
> 
> void child()
> {
>    writeln("thread start");
>    for (int i=0; i<100_000; i++) {};
>    writeln("thread end");
>    throw new Exception("exception from thread");
> }
> 
> If I use spawnLinked, I know the thread ended, but still no original exception. If I change main() to terminate before child(), it actually waits until the child finishes and prints the exception, so there has to be a way.
> 
> -- 
> mk
August 08, 2012
On 08/08/2012 01:52 AM, Martin Krejcirik wrote:

> I meant how can I print the actual exception from the thread, including
> it's error message, stack trace etc.

Catching the exception explicitly and rethrowing would help a little:

// ... at the worker ...
                try {
                    // ...

                } catch (shared(Exception) exc) {
                    owner.send(exc);
                }},

// ... at the owner ...
        receive(
            // ...

            (shared(Exception) exc) {
                throw exc;
            });

Although, I've been bitten by the fact that AssertError is not an Exception, so exceptions thrown by assert checks will continue to surprise. :/

Ali

August 08, 2012
On 8.8.2012 18:15, Ali Çehreli wrote:
>                 } catch (shared(Exception) exc) {
>                     owner.send(exc);

Ahh shared, I've been trying immutable and such. Thanks a lot.

> 
> Although, I've been bitten by the fact that AssertError is not an Exception, so exceptions thrown by assert checks will continue to surprise. :/

Easy, just catch Throwable :-)

cya

-- 
mk
August 08, 2012
On 08/08/2012 12:44 PM, Martin Krejcirik wrote:

> Easy, just catch Throwable :-)

The problem is, Error (and Throwable) should not be caught. There is no guarantee of program behavior when an Error is thrown. At the least, an AssertError is by definition pointing at bad program state so no further action should make sense.

On the other hand, in my case catching by Throwable was the only way I could figure out why my concurrency program was getting stuck. So yeah, I guess the guideline should be don't catch Error in general. :)

Ali

Top | Discussion index | About this forum | D home