www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15104] New: Switching fibers in finally blocks breaks EH

https://issues.dlang.org/show_bug.cgi?id=15104

          Issue ID: 15104
           Summary: Switching fibers in finally blocks breaks EH
           Product: D
           Version: D2
          Hardware: x86
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: druntime
          Assignee: nobody puremagic.com
          Reporter: code klickverbot.at

Consider the following test case:

---
import core.thread : Fiber;

void throwAndYield(string msg) {
  try {
    throw new Exception(msg);
  } finally {
    Fiber.yield();
  }
}

void fiber(string name) {
  try {
    try {
      throwAndYield(name ~ ".1");
    } finally {
      throwAndYield(name ~ ".2");
    }
  } catch (Exception e) {
    assert(e.msg == name ~ ".1");
    assert(e.next);
    assert(e.next.msg == name ~ ".2");
    assert(!e.next.next);
  }
}

void main() {
  auto first = new Fiber(() => fiber("first"));
  auto second = new Fiber(() => fiber("second"));
  first.call();
  second.call();
  first.call();
  second.call();
  first.call();
  second.call();
}
---


Because the current implementation keeps information about the inflight
exceptions in a TLS variable, switching contexts while an exception is in
flight (i.e., from a finally block or dtor) completely breaks EH. More
specifically, exceptions might disappear from one thread and might be appended
to the exception chain of another thread.

The solution is to save/restore the per-stack EH metadata on fiber context
switches. I am not going to fix this for DMD's druntime, but will link the LDC
patch for reference here once it's done.

--
Sep 23 2015