[Issue 21013] New: dwarfeh: Comparing LSDA is too unreliable to determine if two exceptions can be merged
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Sun Jul 5 13:11:52 UTC 2020
https://issues.dlang.org/show_bug.cgi?id=21013
Issue ID: 21013
Summary: dwarfeh: Comparing LSDA is too unreliable to determine
if two exceptions can be merged
Product: D
Version: D2
Hardware: All
OS: Linux
Status: NEW
Severity: major
Priority: P1
Component: druntime
Assignee: nobody at puremagic.com
Reporter: ibuclaw at gdcproject.org
The run-time implementation of D EH personality routines tries to cater for
merging two in-flight exceptions. In order to do this for Dwarf/Unwind EH, it
assumes that each function will have only one LSDA, and it will be unique to
that function.
See [1] for combining two in-flight exceptions before switching to the handler,
and [2] for determining which of the in-flight Exceptions takes precedence when
search for a catch/finally handler.
[1]
https://github.com/dlang/druntime/blob/d3dfa0778fbad77482b0ae8e7e528b55aa417c19/src/rt/dwarfeh.d#L413-L418
[2]
https://github.com/dlang/druntime/blob/d3dfa0778fbad77482b0ae8e7e528b55aa417c19/src/rt/dwarfeh.d#L479-L485
--------------------------------------------------------
Line [1] Breaks if the function is partitioned into two.
e.g:
---
void bug1513a()
{
throw new Exception("d");
}
void bug1513()
{
try
{
try
{
bug1513a();
}
finally
{
throw new Exception("f");
}
}
catch(Exception e)
{
assert(e.msg == "d"); // <-- Assertion failure here
assert(e.next.msg == "f");
assert(!e.next.next);
}
}
---
No combining happens because there are two LSDA's for bug1513().
---
_D4test7bug1513FZv:
push rbp
mov rbp, rsp
call _D4test8bug1513aFZv
jmp .L5
//
// LSDA for bug1513()
//
_D4test7bug1513FZv.cold:
.L5:
...
//
// LSDA for bug1513.cold()
//
---
--------------------------------------------------------
Line [2] breaks if one function is inlined into another.
e.g:
---
void test4()
{
void throw_catch()
{
try
{
throw new MyException;
}
catch (MyException)
{
}
catch (Exception)
{
assert(false); // <-- Assertion failure here
}
}
try
{
try
{
throw new Exception("a");
}
finally
{
throw_catch();
}
}
catch(Exception e)
{
assert(e.msg == "a");
assert(!e.next);
}
}
---
The function throw_catch() is inlined into its parent, and so both now share
the same LSDA. This means that the catch handler for MyException is now
ignored because there's already an in-flight Exception that takes precedence
because they appear to be thrown from the same function.
--
More information about the Digitalmars-d-bugs
mailing list