Bug 15104 – Switching fibers in finally blocks breaks EH
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
x86
OS
All
Creation time
2015-09-23T22:37:00Z
Last change time
2015-10-04T18:19:23Z
Keywords
patch
Assigned to
nobody
Creator
code
Comments
Comment #0 by code — 2015-09-23T22:37:48Z
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.