Bug 22099 – scope(exit) / finally blocks not are always executed inside of a anonymous function

Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2021-07-04T08:39:51Z
Last change time
2023-01-10T08:05:17Z
Keywords
backend
Assigned to
No Owner
Creator
Luis

Comments

Comment #0 by luis.panadero — 2021-07-04T08:39:51Z
Trying this code with dmd v2.097.0 (on Ubuntu x86_64 20.04 LTS) Giving this code : #!/usr/bin/env dub import core.exception; import core.stdc.stdio; import core.stdc.stdlib; import std.stdio : writeln; void main() { auto f = () { int* ptr = cast(int*) malloc(int.sizeof * 1000); try { fprintf(stderr, "Hello\n"); throw new RangeError("bla bla"); } finally { // writeln("Bye 1"); fprintf(stderr, "Bye\n"); free(ptr); } }; try { f(); } catch (RangeError ex) { } } Outputs only "Hello" on console. And running with valgrind, reveals a memory leak as free(ptr) it's never called. ==22254== 4,000 bytes in 1 blocks are definitely lost in loss record 3 of 3 ==22254== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==22254== by 0x14B701: _D1f4mainFZ9__lambda1FNbZv (f.d:15) ==22254== by 0x14B6C2: _Dmain (f.d:27) ==22254== by 0x14C57A: _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZ9__lambda2MFZv (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14C41C: _D2rt6dmain212_d_run_main2UAAamPUQgZiZ7tryExecMFMDFZvZv (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14C4F6: _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14C41C: _D2rt6dmain212_d_run_main2UAAamPUQgZiZ7tryExecMFMDFZvZv (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14C37D: _d_run_main2 (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14C0D9: _d_run_main (in /tmp/.dub/build/f-~master/application-debug-linux.posix-x86_64-dmd_2097-FB7AFBA927D99FA3DDD7307BACA865DA/f) ==22254== by 0x14B77D: main (entrypoint.d:29) ==22254== ==22254== LEAK SUMMARY: ==22254== definitely lost: 4,000 bytes in 1 blocks ==22254== indirectly lost: 0 bytes in 0 blocks ==22254== possibly lost: 32 bytes in 1 blocks ==22254== still reachable: 24 bytes in 1 blocks ==22254== suppressed: 0 bytes in 0 blocks ==22254== Reachable blocks (those to which a pointer was found) are not shown. ==22254== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==22254== ==22254== For lists of detected and suppressed errors, rerun with: -s ==22254== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Removing the comment of the writeln() , does the that the finally {} block being executed as must be. Also, this happens with scope(exit). With ldc2 1.20.1 (DMD v2.090.1, LLVM 10.0.0), the finally block it's always executed.
Comment #1 by moonlightsentinel — 2021-07-04T11:22:08Z
Seems to be a regression from 2.077.1: Up to 2.077.1: Success with output: ----- Hello Bye ----- Since 2.078.1: Success with output: Hello Tagging as backend given that it works with LDC
Comment #2 by bugzilla — 2023-01-10T08:05:17Z
The trouble here is that a RangeError is being thrown. A RangeError is an Error, and finally blocks are not executed when unwinding an Error. The rationale is that Errors are fatal, and may be thrown because the program has entered an invalid state. Executing finally blocks may cause further undefined behavior. Changing the exception type to Exception causes the program to work as expected, as Exceptions execute finally blocks when unwinding. Marked as INVALID.