-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exception stack not cleaned up after return inside of a catch handler with a finally clause #34579
Comments
CCing @JeffBezanson as commit history indicates you added the test case 12806. |
Spent a bit of time trying to simplify this down further. Looks like the actual issue is that the stack doesn't clean up when you do a using Base: catch_stack
function foo()
try
throw("err")
catch
return
finally
end
end
foo()
println(length(catch_stack())) $ julia error.jl
1
$ Seems this isn't actually tied to |
I believe the unique thing in the build environment I've been working in that triggered this (and other) test interaction errors to appear is the fact that it runs isolated from the network. From looking at the code, I believe the lack of a network causes julia to run the test sequentially one on worker. This means that all tests share some global state and causes issues between each other. I would presume whether these issues occur normally or not will otherwise depend on which tests run on which workers. I expect you can test for these failures in a non-isolated build environment by manually hacking test/runtests.jl
to not set |
Very likely this is a bug in lowering. Syntax desugaring turns the try-catch-finally into the nested form function foo()
try
try
throw("err")
catch
return
end
finally
end
end which is then transformed by The following form does not have this problem, so it's some interaction with the finally block where returning from within the function foo()
try
throw("err")
catch
return
end
end |
I spent a while staring at the applicable part of lowering. This is a bug in how lowering's linearization pass for exception stack Specifically, the lowering of To get all this to work there's a rather neat system for tagging the return path and emitting the right code to leave the inner scope of any exception handlers, etc. But the code for popping the exception stack is missing (for Here's a related failing test for function foo()
while true
try
throw("Expected")
catch
try
break
finally
@test length(Base.catch_stack()) == 1
end
end
end
end |
When using `return` or `break` nested inside `finally` handlers, exception stack lowering failed to pop exceptions from the stack correctly: * For `return`, the exception stack was not popped at all. If done inside a loop this could eventually cause the runtime to run out of memory. * For `break`, the exception stack was popped too early, causing subtle inconsistency in intermediate finally handlers. Fix these issues by storing the current exception token stack with the current finally handler information and using it to pop the stack before jumping into the finally block. Fixes #34579
When using `return` or `break` nested inside `finally` handlers, exception stack lowering failed to pop exceptions from the stack correctly: * For `return`, the exception stack was not popped at all. If done inside a loop this could eventually cause the runtime to run out of memory. * For `break`, the exception stack was popped too early, causing subtle inconsistency in intermediate finally handlers. Fix these issues by storing the current exception token stack with the current finally handler information and using it to pop the stack before jumping into the finally block. Fixes #34579
When using `return` or `break` nested inside `finally` handlers, exception stack lowering failed to pop exceptions from the stack correctly: * For `return`, the exception stack was not popped at all. If done inside a loop this could eventually cause the runtime to run out of memory. * For `break`, the exception stack was popped too early, causing subtle inconsistency in intermediate finally handlers. Fix these issues by storing the current exception token stack with the current finally handler information and using it to pop the stack before jumping into the finally block. Fixes #34579
When using `return` or `break` nested inside `finally` handlers, exception stack lowering failed to pop exceptions from the stack correctly: * For `return`, the exception stack was not popped at all. If done inside a loop this could eventually cause the runtime to run out of memory. * For `break`, the exception stack was popped too early, causing subtle inconsistency in intermediate finally handlers. Fix these issues by storing the current exception token stack with the current finally handler information and using it to pop the stack before jumping into the finally block. Fixes #34579 (cherry picked from commit 16ba0dd)
When using `return` or `break` nested inside `finally` handlers, exception stack lowering failed to pop exceptions from the stack correctly: * For `return`, the exception stack was not popped at all. If done inside a loop this could eventually cause the runtime to run out of memory. * For `break`, the exception stack was popped too early, causing subtle inconsistency in intermediate finally handlers. Fix these issues by storing the current exception token stack with the current finally handler information and using it to pop the stack before jumping into the finally block. Fixes JuliaLang#34579
I ran into issues with the
exception
test suite failing in a particular build environment when ran in the complete test suite but not by itself.Through a process of elimination I eventually traced the issue down to test12806 in core.jl leaving things on the exception stack.
The following
error.jl
code, which is just coretest12806
followed by the very first exception test, seems to reliably demonstrate the issue for both 1.3.0 and 1.3.1 across several linux distributions (nix, gento, arch, debian).Here is the output I get from running it
The text was updated successfully, but these errors were encountered: