Why does the Visual Studio 2010 debugger not pick up debug symbols for handling exception in F# sequence?
-
28-10-2019 - |
Question
In Visual Studio 2010, the following F# sequence works as expected in Release mode (ignores UnauthorizedAccessException), but does not work correctly in Debug mode (breaks on UnauthorizedAccessException, even if I have set "Common Language Runtime Exceptions: Thrown = false, User-Unhandled = true").
open System
open System.IO
module private MyTestModule =
let rec private getAllFiles dir = seq {
if String.IsNullOrWhiteSpace dir |> not then
let getAuthorizedItems getItems dir =
try getItems dir
with :? UnauthorizedAccessException -> [||]
// Debugger stops here on UnauthorizedAccessException, but shouldn't...
yield! getAuthorizedItems Directory.GetFiles dir
for subDir in getAuthorizedItems Directory.GetDirectories dir do
yield! getAllFiles subDir }
// etc.
However, if I do not nest the getAuthorizedItems function inside the sequence, but place it at module level instead, the debugger works correctly.
Note:
- I have looked at the generated IL code, and the exception handler is where it should be in both cases (is not modified/optimized in any way);
- I know that System.Core must be preloaded in order for sequences to be displayed correctly in the debugger, but that is not related to my issue.
Are there any special rules for handling exceptions in sequences at debug time in F#?
Edit
After my reporting the issue, the F# team very quickly started to track it. It seems to be a minor bug related to the fact that, in Debug mode, some of the generated code is marked as ‘External Code’, even though it is user code. For the time being, one can use the workarounds suggested in pad's answer. Another workaround ist to turn off "Enable Just My Code" in the VS debugging options.
Solution
I'm able to reproduce the bug on my machine using F# 2.0/.NET 4.0 without VS2010 SP1 installed. It could be the case that this bug has been fixed in VS2010 SP1 as @svick couldn't reproduce it. It turns out this bug is still present after VS2010 SP1 update.
I think it's a bug of handling exception in nested functions inside sequence expression, changing the nested function to catch any exception doesn't affect the behaviour:
let getAuthorizedItems getItems dir =
try getItems dir
with ex -> [||]
This is a minor bug; you can bypass it in many ways:
- It works in Release mode, inside fsi and even runs in Debug mode outside Visual Studio.
- Declaring the nested function as
inline
makes it work in Debug mode. - Turning on
Optimize code
option makes it work again. - Not using nested functions inside
seq
also helps.
If it hasn't been fixed, I suggest you file a bug report at fsbugs at microsoft dot com.