Coroutines and exceptions

mclysenk at mtu.edu mclysenk at mtu.edu
Mon May 1 20:52:54 PDT 2006


In article <e2vh64$2vhe$1 at digitaldaemon.com>, Lars Ivar Igesund says...
>
>Daniel Keep wrote:
>
>> 
>> Hi.
>> 
>> I've been playing around with an implementation of coroutines in D the
>> last day or two, and I've got it to the point where it works pretty well
>> under gdc, and under dmd with a few bugs to track down.  But I've hit a
>> brick will with exceptions.
>> 
>> See, I was kinda hoping that D found exception handlers by going back up
>> the stack frames... although after pouring over the disassembly in gdb,
>> it looks like D registers the exception handlers as it meets them.
>> 
>> The problem with this is that the coroutine library allows you to jump
>> from one part of the code to another, which ends up screwing up the
>> order of exception handlers.  For example (simplified, mind you):
>> 
>> void coro_a()
>> {
>>     try
>>     {
>>     co_call(main); // Jump back into main just after co_call
>>     }
>>     except( Exception e )
>>     {
>>         writefln("Exception in coro_a: %s", e.toString());
>>     }
>> }
>> 
>> void main()
>> {
>>     try
>>     {
>>         co_call(coro_a); // Jump into coro_a
>>         throw new Exception("Oh noes!");
>>     }
>>     catch( Exception e )
>>     {
>>         writefln("Exception in main: %s", e.toString());
>>     }
>> }
>> 
>> If you run that, you end up getting "Exception in coro_a: Oh noes!"
>> instead of "Exception in main: Oh noes!" as you would expect.
>
>I have been working on getting Mikola Lysenko's StackThread working on
>Linux, and I just tested the exception handling (which I did not have to do
>anything with, it just worked the way he had implemented it. Unless this
>way is not what you want, and your couroutines might not be altogether the
>same thing as this StackThread (I tried to send you a mail, but don't know
>if it will reach you...). Anyway, the test code goes like this (in the
>unittest):
>
>
>try {
>    void exceptions()
>    {
>        writefln("Testing exception handling...");
>        throw new Exception(std.string.format("Test exception, line %s",
>__LINE__));
>        StackThread.yield();
>    }
>
>    StackThread t = new StackThread(&exceptions);
>    t.resume();
>    StackThread.run();
>
>    assert(false);
>}
>catch(Exception e)
>{
>    writefln(e);
>}
>
>And the result is this:
>
>Testing exception handling...
>Test exception, line 412
>
>The assert is not triggered.
>
>I do agree that your result seems somewhat strange, though...
>
>-- 
>Lars Ivar Igesund
>blog at http://larsivi.net
>DSource & #D: larsivi

That is because on windows you need to save the stack top & bottom when you
change contexts.  They are stored at FS[4] and FS[8].  Also it would be a good
idea to relink the SEH chain when you create a new coroutine, so the top level
is tied to the SEH that originally called the coroutine.  As far as I can tell,
this behaviour is not very well documented, but for more info on structured
exception handling, you can check out
http://www.microsoft.com/msj/0197/exception/exception.aspx .

I'm currently working on extending the StackThread system to support priority
based scheduling and Linux.  At the moment, I have a specification drawn up,
along with a basic architecture/implementation.

-Mikola Lysenko





More information about the Digitalmars-d mailing list