-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
Make order of ConfigurationDoneRequest and LaunchRequest deterministic #4902
Comments
@andrewcrawley here is the corresponding issue from 2016! I've moved it to the February milestone. |
vsdbg is another example of an adapter that sends the "initialized" event during processing of the "launch" request, and I believe MIEngine + OpenDebugAD7 also exhibits this behavior. If an adapter advertises that it supports "configurationDone", but begins executing the debuggee before receiving that request, it seems pretty clear to me that this is a bug in the adapter. Running the debugee obviously requires complete configuration information, so if configuration is still ongoing, the debuggee should not be running. I would expect that in the case that the debug adapter receives "launch" before "configurationDone", it would:
|
I am not following how the first scenario above could work reliably. If I am reading the following bolded section of the protocol documentation for InitializedEvent correctly --
Then to me that means that a debug adapter isn't allowed to send the InitializedEvent before it sends InitializeResponse. If I am reading things correctly -- there would be a race in scenario 1 since just because the debug adapter sent the InitializedEvent right away doesn't mean the client will actually get that event in time to know that it needs to delay sending launch until all the breakpoints and other configuration options have been sent. |
@gregg-miskelly thanks for adding the excerpt from the I had hoped that the implementation of mock-debug would actually stick to the spec, but it does not. It failed the "(but not before the InitializeRequest has finished)". Moving the line that emits the Trying to delay the Making this approach work for the "late" case, would require that the frontend receives the information whether it is dealing with the "early" or the "late" case. This would require another capability... which I don't like. @andrewcrawley this means that I've (finally!) arrived at the same conclusion as you did already a while ago: the problem cannot be (easily) solved on the frontend side but must be fixed in mock-debug. So today I tried various approaches to delay the But in the end I found a wait/notify-based fix that is small and simple: https://github.com/Microsoft/vscode-mock-debug/blob/9d378d6aa00982c565b9c19323a7882538a6063a/src/mockDebug.ts#L111-L134 @andrewcrawley Please try whether the latest version of mock-debug works for you now. |
No, it still doesn't work in the VS host. We wait for a response to the "launch" request before we proceed with initialization, so with your fix, the launch request blocks for 1000ms, then continues anyway, still before the "configurationDone" request. Would it work to send the response, then do your wait before starting the runtime? Here's the log from our side:
|
Delaying the "initialisation" to occur after the "launch" request has send its response, sounds wrong. Does the VS host always delay the processing of the "initialisation" after the "launch" response is received? "launch" means "launch the debuggee". It does not mean "remember the launch config for some later point in time". If the launching fails, the error is reported as the "launch" response. Returning a launch error as a "configurationDoneResponse" will confuse frontends as it is not specified that a launch error can be returned as such.
is "no". In addition, if breakpoints arrive as part of the "initialisation" after the program has beed launched, there is the danger that breakpoints in the startup sequence are not hit because execution is already beyond that. We have introduced the "initialiseEvent" to avoid the problem that the DA has to remember all config information until it can actually be used. With the "initialiseEvent" the DA can request the information at a time when it is able to use it. If this "initialise" sequence is now delayed by the frontend until the "launch" request has sent its response, this means for some DAs that they now have to remember all launch information until the "configurationDone" request is called. This basically negates the reason why the "initialiseEvent" got introduced in the first place. |
To recap - from our earlier conversation, it sounds like the logic in VS Code is basically:
In the case of an adapter that tries to do "early" initialization by sending the
In this case, the debuggee is now running, but hasn't received the As you mentioned in our earlier conversation, it may be possible for the host to guess (based on the ordering of events and responses it receives) when it's safe to send the "launch" request, but this would break down if an adapter returns an unexpected message ordering. This may be acceptable if you want to specify that certain orderings are just "wrong", but this would need to be made clear in the protocol spec - right now it's very open to interpretation. The solution I have proposed (don't do anything that requires valid configuration until the
This maps very closely to the "late" initialization sequence. I surveyed various popular debug adapters and found the following implementations:
Are you aware of other adapters that use "early" initialization or another weird sequence of events? |
No, the logic (defined in the spec and embodied in VS Code) is this:
Concurrent to this the DA may send an initialise event to trigger the "initialise" sequence of VS Code. In contrast VS uses the "don't do anything that requires valid configuration until the "configurationDone" request is received" approach. This changes the semantics of the "launch" request significantly (which would result in a - may be breaking - change of the DAP spec) because "launch" doesn't do anything but collecting parameters. "configurationDone" becomes the real work horse now (another change of the DAP spec). BTW, what is your sequence if a DA does not request "configurationDone" (which is the default)? I'm not saying that the current VS Code approach is any better than your approach. I just don't understand what effect your approach has on any existing DAs out there. What I know is that all existing DAs (even the broken mock-debug) work with the logic implemented by VS Code. Your comments about my mock-debug fix: (Please ignore the 1000 ms timeout for a moment). |
I think we're in agreement on the logic, my formatting is just a bit different. If you disagree, can you clarify what I got wrong? The VS host requires an
If an adapter doesn't support I can investigate making the VS host not block on the |
Yes, we are in agreement with the logic and you've clearly stated where VS and VS Code differ:
So today the exact VS sequence is probably more this:
Important consequence: Initialisation always starts after launch response received (which means that every(!) DA has to move the actually launching of the debuggee into the configurationDone request). Those that don't do this might receive breakpoint etc. too late. And the VS Code sequence is:
Important consequence: Initialisation starts immediately and can occur before or after the launch response arrives. This makes it possible to actually launch the debuggee in the launch request (after waiting for the configurationDone request to arrive). So if you could get the VS host to work when not blocking on the launch request, we could be very sure that the VS and VS Code behave identically and that all DAs would work fine in the VS host. |
I'm resolving this issue by specifying two constraints:
The following sequence diagrams show the exact sequence for the "early" and the "late" case: |
Currently the order of ConfigurationDoneRequest and LaunchRequest is not deterministic, that means it is possible that a ConfigurationDoneRequest comes after the LaunchRequest. This is problematic because only a ConfigurationDoneRequest indicates that all breakpoints have been registered and that a LaunchRequest is able to hit all those breakpoints. If the ConfigurationDoneRequest comes after the LaunchRequest some breakpoints might be missed.
There are two scenarios to consider:
From the first case it looks like the frontend could always wait with calling LaunchRequest until ConfigurationDoneRequest has been ended. But this would not work with the second case.
/cc @isidorn
The text was updated successfully, but these errors were encountered: