digitalmars.D.bugs - [Issue 21013] New: dwarfeh: Comparing LSDA is too unreliable to
- d-bugmail puremagic.com (114/114) Jul 05 2020 https://issues.dlang.org/show_bug.cgi?id=21013
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 puremagic.com Reporter: ibuclaw 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. --
Jul 05 2020