Does stepping through async code in Xcode 13 or 14 work for anyone? Apple seems to think it works (they keep rejecting the feedback I send), but it just doesn't work for me. I opened a new bug about the same issue today (because they closed my previous one), wherein I can't step over an await call; the debugger just continues as if I had told it to Continued instead of step over.
Trying things out with a simple macOS app project, it's a bit better. In a unit test, I can sort-of step over an async call, but it takes three invocations of the step over command. Attempting to Run after that results in a runtime error that it couldn't set a breakpoint ("step over failed (Could not create return address breakpoint.)"). Continuing after that things complete normally. I am unable to step into the call at all
A similar call from a running SwiftUI app has to be stepped over twice before the "step over failed" error. It also cannot step in without error.
In my large Vapor app, stepping into or over just results in behavior as if I had Continued.
Sure! FB10012674 was the earlier one that got closed, demonstrating a number of issues around stepping and breaking in async code. FB10899199 is the one I opened today just about stepping over the call in 14b4.
I have found that I can't run any LLDB commands when I stop at a breakpoint inside of an async context.
doing something as simple as po someVariable just gives me errors:
warning: Swift error in scratch context: error: failed to load module 'MyApp'
.
Shared Swift state for MyApp has developed fatal errors and is being discarded.
REPL definitions and persistent names/types will be lost.
error: expression failed to parse:
unknown error
Just to feed an already raging fire... I don't think debugging async methods works in any fashion for anybody. It's clear no amount of feedback posted here, submitted via Feedback Assistant, or otherwise is going to change it. There are numerous posts on here asking, and quite a few just complaining, about it. I think we're resigned to just wait until they get around to it, if ever.
Now to be productive, I can suggest a workaround you might already know... use "Continue program execution" instead of stepping. I.e. you set a breakpoint (even if it's the next line) and continue; this seems to work. Maybe there's an LLDB macro "breakpoint next line and continue" to be made. I don't know enough about LLDB to find the next line in source terms to make one.
Apologies, it looks like I missed this thread the first time around (probably because it wasn't tagged with the LLDB topic). I did some experiments and I think I can reproduce the behavior that @JetForMe is seeing where step-over in an async function behaves like a step-in.
@BrentM The error you're quoting most likely has nothing to do with async nature of the context, but rather with your project configuration. First step to sorting that out would be to run (lldb) swift-healthcheck after the error. If you aren't comfortable with sharing it on the LLDB forum here, you can also file a feedback with Apple (assuming you're on an Apple platform).
@Kevin_Wooten Can you describe what kinds issues you are running into? Are you referring to the step-over behavior described by @JetForMe, or are there other issues you would like to share with us?
Stepping in an async method may work for one or two lines of code then, especially when stepping over an await or try, you will land in some (seemingly random) assembler listing with an error about not being able to determine the backtrace pointer
The thing is, the "step over" seems to be running ahead and trying to "step out" of the current function instead; this could also just be something about the way LLDB implements step over.
This is 100% of the time. I have never been able to properly use the step in/out/over without running into this issue after only a couple attempts. This is demonstrated in Swift Packages, Xcode Swift Frameworks, and Apple platform applications.
And I do apologize for the negativity but there are numerous posts in these forums about the broken state of Xcode/LLDB, and I'm just realizing the one that comes to mind the easiest was started by @JetForMe as well .
Swift, like Danny Glover in Lethal Weapon, is too old for this sh*t
It's hard to give any meaningful feedback about what does and doesn't work because my experience has just been that nothing works other than breakpoints. Both step-over and step-in will sometimes behave as if I Continued, and sometimes result in the program being paused in the wrong place. Occasionally the program livelocks in the async event loop and requires a pause/continue to get it unstuck. In no circumstances have I seen stepping through async code actually work.
As others have said, stepping through async code generally doesn't work (it may just continue execution, it may stop somewhere random and unexpected, often in assembly code somewhere), but especially if stepping over (or into) an await call. Similarly, stepping up/out of an async method results in stopping somewhere randomly (and often in an error state the prevents resumption of execution).
Setting a breakpoint seems to be the only reliable way to stop on a given line. If you then choose to continue execution, it will often stop at that same breakpoint 1-3 more times, even though that method is not called again; that is, as a matter of resuming execution, it stops at that breakpoint.
If you could permit me an, admittedly hyperbolic, analogy...
If you were at a scrapyard and you are staring at a vehicle that has been smashed into a cube... how would you answer a mechanic who asks... "So, tell me specifically what's wrong with it so I can fix it?"
It seems everybody here is saying the same thing. If specific examples are needed many are cited and all can be observed by simply attempting to use it.
There’s no need to resort to hyperbole. It’s perfectly reasonable to be frustrated at the debugger if it reliably fails in common scenarios. But when it comes time to report the bug, explain how it fails in a step-by-step manner. It is quite possible there are actually multiple causes of failure, and specific repro steps only trigger one of them.
Thanks @tgoyne. This is the behavior I mentioned above that I can reproduce where step-over behaves like step-in. What I'm curious about is whether that's the only issue, or whether there are other issues that we should know about.
Press "step over". The cursor doesn't actually move, but sometimes this happens with synchronous code due to e.g. computed properties, so I'm not too worried about that.
Press "step over" again. Instead of moving to line 3, you end up in some assembly listing. I see the cursor on this line (x86-64 Ubuntu 22.04):