Skip to content
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

No stdout when running gdb/gdbserver. #827

Closed
d-bahr opened this issue Jun 14, 2017 · 18 comments
Closed

No stdout when running gdb/gdbserver. #827

d-bahr opened this issue Jun 14, 2017 · 18 comments
Assignees

Comments

@d-bahr
Copy link

d-bahr commented Jun 14, 2017

I have an ARM processor that is my target for debugging. I can successfully copy an executable to the target and debug it using gdbserver running on the target and gdb running on the host. The host is a Windows computer running WSL; the code is cross-compiled in WSL and all of the copying and debugging commands are also executed from within WSL. When I debug, I can see the gdb commands in the Debug Console window, but I do not see my application output (stderr and stdout).

This is a snippet from my launch.json file:

{
    "version": "0.2.0",
    "configurations": [
    
        {
            "name": "Launch ARM",
            "type": "cppdbg",
            "request": "launch",
            "program": "/mnt/c/path/to/executable",
            "args": [],
            "stopAtEntry": true,
            "cwd": "/mnt/c/path/to/cwd",
            "environment": [],
            "externalConsole": true,
            "filterStderr": true,
            "filterStdout": true,
            "sourceFileMap": {
                "/mnt/c/path/to/cwd": "${workspaceRoot}"
            },
            "preLaunchTask": "ARM Install",
            "windows": {
                "MIMode": "gdb",
                "pipeTransport": {
                    "pipeCwd": "${workspaceRoot}",
                    "pipeProgram": "C:/Windows/Sysnative/bash.exe",
                    "pipeArgs": ["-c"],
                    "debuggerPath": "/usr/bin/gdb-multiarch"
                },
                "setupCommands": [
                    {
                        "description": "Enable remote ARM architecture",
                        "text": "set architecture arm",
                        "ignoreFailures": false
                    },
                    {
                        "description": "Start remote debugging",
                        "text": "target remote | ssh username@hostname gdbserver - /path/to/remote/executable",
                        "ignoreFailures": false
                    }
                ]
            }
        }
    ]
}

Changing externalConsole doesn't seem to have an effect; I never see an external console opening nor do I see the output in the Output or Debug Console windows. This option seems to be ignored.

If I run the debugging commands from Windows command line (as in the following example), I can see the program output just fine.

C:\Windows>C:\Windows\System32\bash.exe -c /usr/bin/gdb-multiarch
...
(gdb) set architecture arm
The target architecture is assumed to be arm
(gdb) target remote | ssh username@hostname gdbserver - /path/to/remote/executable
Remote debugging using | ssh username@hostname gdbserver - /path/to/remote/executable
...
(gdb) c
Continuing.
[Program output here.]

I should also note that when I ssh into the target and run gdb natively, the application output is interleaved with the gdb output in the Debug Console, but it never shows up in a separate terminal, even with "externalConsole": true.

My current workaround is to run gdb natively on the target and view the application output in the Debug Console, but it would be nice to view the application output in a separate terminal.

@d-bahr
Copy link
Author

d-bahr commented Jun 15, 2017

I've been able to reproduce this running locally with a simple gdb on my host machine. The application output and gdb output are both in the Debug Console; externalConsole seems to have no effect.

Sample launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch x64",
            "type": "cppdbg",
            "request": "launch",
            "program": "/path/to/executable",
            "args": [],
            "stopAtEntry": true,
            "cwd": "/path/to/cwd",
            "environment": [],
            "externalConsole": true,
            "filterStderr": true,
            "filterStdout": true,
            "windows": {
                "MIMode": "gdb",
                "pipeTransport": {
                    "pipeCwd": "${workspaceRoot}",
                    "pipeProgram": "C:/Windows/sysnative/bash.exe",
                    "pipeArgs": ["-c"],
                    "debuggerPath": "/usr/bin/gdb"
                }
            }
        }
    ]
}

@pieandcakes
Copy link
Contributor

@d-bahr Setting externalConsole to true tells us to send -gdb-set new-console on only in the instance of local launching. In the remote (pipeTransport scenario), this doesn't make sense and is ignored since gdb doesn't know where to open the console.

Is there a reason why you are using two different remoting processes? Could you use the pipeTransport option with a Windows SSH program (such as plink.exe) to directly connect to your remote gdb arm instance or use the miDebuggerServerAddress to directly connect to the remote arm gdbserver? or are you looking for some way to include WSL/Bash on Windows in the equation?

@pieandcakes pieandcakes self-assigned this Jun 16, 2017
@d-bahr
Copy link
Author

d-bahr commented Jun 18, 2017

@pieandcakes The decision to avoid gdbserver basically boils down to wanting VSCode to be in charge of starting the debugging session. I could start gdbserver manually on the remote ARM, but that's an extra step that I would prefer to eliminate. Also, it seems that gdbserver is significantly slower than gdb to launch a new debugging session (this is related to our setup; not related to VSCode). So that explains why I'm not using miDebuggerServerAddress.

I was using plink.exe before upgrading to the Windows 10 Creator's update because of the issues with forwarding stdin/stdout with bash.exe. I wasn't able to quite get it working with externalConsole at the time (I think because externalConsole was still a new feature that wasn't fully baked yet). That said, I don't really have anything against plink.exe -- I've just been on a WSL kick lately. I'm a little confused though by why plink.exe should be any different than bash.exe? It seems like both of them should effectively do the same thing.

@tmandry
Copy link

tmandry commented Jul 15, 2017

Maybe a separate issue, but I have noticed that stderr does not show up in the debug console (or anywhere) at all on Linux (CentOS 7.2).

When the process being debugged prints to stdout, it does show up for me. However, if stdout gets flushed in between newlines (so a partial line is output by the process), it interferes with the MI output, causing the debugger to miss important events (like stopped on solib-event).

@nikitablack
Copy link

nikitablack commented Jul 19, 2017

Same here. When I run gdbserver in docker container and an executable on the host can't see std::cout output.

@pieandcakes
Copy link
Contributor

@nikitablack So it looks like gdbserver is not sending back the stdout text to gdb. I see it in the docker container if its running in a separate window but gdb gets no notification of the output and as such we don't have anything to show you.

@pieandcakes
Copy link
Contributor

@tmandry That might be a bug. Can you open a separate issue about stderr not appearing?

@pieandcakes
Copy link
Contributor

@d-bahr I think my comment to @nikitablack is the same reason why you can't see it. It seems like gdbserver is not sending back stdout or stderr output to gdb, which in turn is communicating with VSCode which is why it isn't showing up in the console. There needs to be a way to tell gdbserver to send the debuggee's stdout/stderr back to gdb itself.

@d-bahr
Copy link
Author

d-bahr commented Jul 21, 2017

@pieandcakes That makes sense. A possible workaround would be to force gdbserver/gdb to save stdout/stderr to a specific tty and then tell VSCode to open the tty, but I don't think VSCode supports that.

@d-bahr
Copy link
Author

d-bahr commented Jul 21, 2017

I can start a gdb session with a specific tty for stdout like so:
gdb -tty /dev/myTTY /my/application
If I could tell VSCode somehow to open up /dev/myTTY that would be good enough for me. Alternatively, if I could automatically determine which integrated or external console was already open in VSCode, I could pass it to gdb directly.

@seungha-yang
Copy link

@d-bahr
Very helpfull comment for me !!
I also have trouble in using vscode with wsl (no gdb stdout on debug terminal)
As a temporal solution, I can see gdb stdout :)
That is, I explicitly tell currently opened bash on VSCode to gdb by

"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "c:\Bash\bash.exe",
"pipeArgs": ["-c"],
"debuggerPath": "/usr/bin/gdb --tty=/dev/tty3"
}

But supporting this by vscode without explicit "--tty" command seems to be required feature

@d-bahr
Copy link
Author

d-bahr commented Feb 16, 2018

Following up with some new information...

I have been able to reproduce on a native linux host. My launch.json looks roughly like this:

{
    "version": "0.2.0",
    "configurations": [
    
        {
            "name": "Launch ARM",
            "type": "cppdbg",
            "request": "launch",
            "program": "/path/to/executable",
            "args": [],
            "stopAtEntry": true,
            "cwd": "/path/to/cwd",
            "environment": [],
            "externalConsole": true,
            "filterStderr": true,
            "filterStdout": true,
            "logging": {
                "engineLogging": true,
                "trace": true,
                "traceResponse": true,
                "programOutput": true
            },
            "preLaunchTask": "ARM Install",
            "linux": {
                "MIMode": "gdb",
                "miDebuggerPath": "/usr/bin/gdb-multiarch",
                "setupCommands": [
                    {
                        "description": "Enable remote ARM architecture",
                        "text": "set architecture arm",
                        "ignoreFailures": false
                    },
                    {
                        "description": "Start remote debugging",
                        "text": "target remote | ssh username@hostname gdbserver - /path/to/remote/executable",
                        "ignoreFailures": false
                    }
                ],
                "launchCompleteCommand": "None"
            }
        }
    ]
}

I see with logging enabled that the stdout is getting sent from gdbserver to gdb:

1: (26303) <-1031-exec-continue
1: (26304) ->1031^running
1: (26304) ->*running,thread-id="all"
1: (26315) 1031: elapsed time 11
 R: {"success":true,"message":null,"request_seq":15,"command":"next","body":null,"running":false,"refs":null,"seq":0,"type":"response"}
1: (26371) ->(gdb)
1: (26515) ->&"Hello World\n"
1: (26515) ->&"blah blah blah...\n"
1: (26515) ->&"\n"

So it seems that gdb is receiving stdout, but I suppose that either the MI engine or VSCode isn't parsing it out. My suspicion is that the MI engine isn't parsing it correctly because it isn't in the right output format, e.g.:

E output: {"category":"stdout","output":"\nHello World","data":null,"type":"output"}

It seems reasonable to me to simple allow any output in the (#####) ->&"" format to be dumped to the console, maybe with some sort of option in launch.json. Or maybe there's some configuration for the MI engine that I'm missing.

@alan23273850
Copy link

For @pudding8757 's answer, I specify my debuggerPath as follows and it works!

"debuggerPath": "stdbuf -i0 -o0 -e0 /usr/bin/gdb"

stdbuf here is used to disable buffer of all three channels.

@mysterytony
Copy link

For @pudding8757 's answer, I specify my debuggerPath as follows and it works!

"debuggerPath": "stdbuf -i0 -o0 -e0 /usr/bin/gdb"

stdbuf here is used to disable buffer of all three channels.

This works for me! You deserve a thousand likes!

@tak2siva
Copy link

tak2siva commented Feb 22, 2019

For @pudding8757 's answer, I specify my debuggerPath as follows and it works!

"debuggerPath": "stdbuf -i0 -o0 -e0 /usr/bin/gdb"

stdbuf here is used to disable buffer of all three channels.

@alan23273850 It's not working for me :(

@RafaGago
Copy link

RafaGago commented Feb 17, 2020

I'm having this error too.

In my case I'm manually running gdbserver through a pipe to docker like this:

"customLaunchSetupCommands": [
      {
        "description": "Pipe launch gdbserver",
        "text": "target remote | docker exec -i <container> gdbserver - ${workspaceFolder}/<app>",
        "ignoreFailures": false
      },
      {
        "description": "Some apps include relative dirs",
        "text": "cd ${workspaceFolder}",
        "ignoreFailures": false
      },
      {
        "description": "Stop at main",
        "text": "b main",
        "ignoreFailures": false
      }
    ],

I can't modify the container and it has no network connectivity. That's my reason for piping "target remote" through docker exec gdbserver.

I too see that the actual output is reaching vscode with lines like this one:

1: (25102) ->&"[----------] 5 tests from MyTest (2563 ms total)\n"

@github-actions
Copy link

github-actions bot commented Dec 9, 2020

This issue has been closed automatically because it's labeled as 'external'.

@github-actions github-actions bot closed this as completed Dec 9, 2020
@user-name-is-taken
Copy link

user-name-is-taken commented Mar 2, 2021

To make gdb ignore this error use:

"configurations": [
{
...
  "setupCommands": [
      {
         "description": "disable pipe",
         "text": "handle SIGPIPE nostop",
         "ignoreFailures": true
      }
    ]
...
}
]

https://stackoverflow.com/questions/18935446/program-received-signal-sigpipe-broken-pipe/18963142

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants