emacs-lsp / dap-mode

Emacs :heart: Debug Adapter Protocol
https://emacs-lsp.github.io/dap-mode
GNU General Public License v3.0
1.29k stars 180 forks source link

Deserialization exception on working launch.json file #407

Open xgroleau opened 3 years ago

xgroleau commented 3 years ago

I'm trying to launch a vscode debug configuration on emacs, the configuration works on vscode without any issues.

When I launch dap-debug, then select the C++ Launch configuration, an error occurred the error "Debug session process exited with status: Killed" is shown in the bottom mini buffer.

I'm a bit confused to why it works on vscode and not emacs. The error seems to be related to the C# Json library used, so maybe the cpptools-setup is outdated compared to vscode. I'm pretty new to elisp so I've had some trouble finding more information.

I've enabled cpptools using

(require 'dap-cpptools)

and then

M-x dap-cpptools-setup

The .vscode/launch.json file

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "C++ Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "/home/xgroleau/Documents/HiveMind/build/src/hive-mind.elf",
            "args": [],
            "stopAtEntry": true,
            "cwd": "/home/xgroleau/Documents/HiveMind",
            "environment": [],
            "externalConsole": false,
            "debugServerArgs": "-f /home/xgroleau/Documents/HiveMind/cmake/openocd/stm32_f4.cfg -c init -c \"reset init\"",
            "serverLaunchTimeout": 20000,
            "filterStderr": true,
            "filterStdout": false,
            "serverStarted": "target halted due to debug-request, current mode: Thread",
            "preLaunchTask": "make",
            "setupCommands": [
                { "text": "-target-select remote localhost:3333", "description": "connect to target", "ignoreFailures": false },
                { "text": "-file-exec-and-symbols /home/xgroleau/Documents/HiveMind/build/src/hive-mind.elf", "description": "load file", "ignoreFailures": false},
                { "text": "-interpreter-exec console \"monitor endian little\"", "ignoreFailures": false },
                { "text": "-interpreter-exec console \"monitor reset\"", "ignoreFailures": false },
                { "text": "-interpreter-exec console \"monitor halt\"", "ignoreFailures": false },
                { "text": "-interpreter-exec console \"monitor arm semihosting enable\"", "ignoreFailures": false },
                { "text": "-target-download", "description": "flash target", "ignoreFailures": false }
            ],
            "logging": {
                "moduleLoad": true,
                "trace": true,
                "engineLogging": true,
                "programOutput": true,
                "exceptions": true
            },
            "linux": {
                "MIMode": "gdb",
                "MIDebuggerPath": "/home/xgroleau/bin/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi-gdb",
                "debugServerPath": "openocd"
            },

        }

    ]
}

The exception in the output buffer

Warning (emacs): Initialize request failed: Exception occurred: 'Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'OpenDebugAD7.MILaunchOptions+JsonCommand[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'setupCommands.text', line 1, position 604.
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00370] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, System.Object target) [0x00061] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) [0x00267] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00158] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000d9] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00053] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <2781d1b198634655944cdefb18b3309b>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <2781d1b198634655944cdefb18b3309b>:0 
  at OpenDebugAD7.MILaunchOptions.CreateLaunchOptions (System.String program, System.String workingDirectory, System.String args, System.Boolean isPipeLaunch, System.Boolean& stopAtEntry, System.Boolean& isCoreDump, System.Boolean& debugServerUsed, System.Boolean& isOpenOCD, System.Boolean& visualizerFileUsed) [0x00022] in <d80967093d2149f58646b3f4c3b3e132>:0 
  at OpenDebugAD7.AD7DebugSession.HandleLaunchRequestAsync (Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.IRequestResponder`1[TArgs] responder) [0x0026b] in <d80967093d2149f58646b3f4c3b3e132>:0 '

I'm not sure if this is the right place to post the issue since it comes from an external library, but it works on vscode. If not, I will close the issue.

nbfalcon commented 3 years ago

Could you try checking out my bugfix branch ("bugfix/launch-json-empty-array" of this repository) and check if it works? This is indeed a bug in dap-mode, probably caused due to the empty arrays. If you cannot do that, a workaround would be to remove empty arrays ("args", ...).

These are the git command you'll need:

$ cd $PATH_TO_DAP_GIT_CHECKOUT
$ git fetch --all
$ git checkout bugfix/launch-json-empty-array

Then you'll have to make your Emacs use the new version of dap-mode somehow, which I'll assume you know how to do (if not, you may ask, in which case I'll provide additional guidance).

xgroleau commented 3 years ago

I can confirm that the fix works! Thanks for the fast response. Should I close the issue now or after the PR?

nbfalcon commented 3 years ago

I'd leave it open, given that the fix isn't in master. The problem here is that using arrays might break something else, which will need more testing.

nbfalcon commented 3 years ago

Are you referring to my bugfix branch or to my workaround of deleting "args"?

xgroleau commented 3 years ago

Sorry I wasn't clear. I've pulled your bugfix branch and it works.

nbfalcon commented 3 years ago

Great. More testing will be necessary before this can go into master.

galorojo commented 3 years ago

Hello @nbfalcon,

I'm hitting this same issue now and was wondering why the bugfix branch is gone but not merged into master? Did you find any issues with it?

In my case, the problematic launch.json file was:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C++ launch",
      "type": "cppdbg",
      "request": "launch",
      "program": "${workspaceFolder}/pretty_printers_test/main.out",
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "externalConsole": false,
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

For the record, empty arrays ("args": [], and "environment": [],) were working fine on master for me. The thing that triggered the exception was adding the "setupCommands" block.

I've tested the fix proposed in 096ba8b, that makes the exception go away and I do get pretty printing (i.e. the "setupCommands" block does what it's supposed to, so the fix works OK for my toy example test.

My Emacs version is GNU Emacs 27.0.50 (build 6, x86_64-pc-linux-gnu, GTK+ Version 3.24.9) of 2019-07-11

I can provide any extra information if you need it or help doing any specific tests on the patched version of `dap-launch.el. Thanks

nbfalcon commented 3 years ago

I have no idea why the branch was deleted, and I have recreated it in my fork.

@yyoncho do you think something might break in dap-mode if an array is passed instead of a list, e.g. for some :args field?

nbfalcon commented 3 years ago

Specifically dap-java.

yyoncho commented 3 years ago

in general, an empty vector will be serialized to [] in json while empty list will end up nil. So this might potentially break the java server.