Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Debugging not working with ruby on rails #426

Closed
qortex opened this issue Feb 12, 2019 · 30 comments
Closed

Debugging not working with ruby on rails #426

qortex opened this issue Feb 12, 2019 · 30 comments

Comments

@qortex
Copy link

qortex commented Feb 12, 2019

Your environment

  • vscode-ruby version: 0.21.0
  • Ruby version: 2.6.0
  • Ruby version manager (if any): rbenv
  • VS Code version: 1.31.0
  • Operating System: Fedora 29
  • Using language server? Yes

Expected behavior

Should break on breakpoint.

Actual behavior

Does not break on breakpoints after starting rails server and making a request that runs the code where I want a breakpoint.

If I add the breakpoint before running the debugger, it hangs without more context when supposedly hitting the breakpoint.

If I add the breakpoint after running the debugger, the breakpoint is simply ignored.

My config is:

{
  "name": "Rails server",
  "type": "Ruby",
  "request": "launch",
  "program": "bin/rails",
  "cwd": "${workspaceRoot}",
  "showDebuggerOutput": true,
  "args": [
    "server"
  ]
}

In the debug console, I properly have Fast Debugger (ruby-debug-ide 0.6.1, debase 0.2.2, file filtering is supported) listens on 127.0.0.1:1234.

Tried removing / adding byebug, debase and ruby-debug-ide from Gemfile with no luck.

@qortex
Copy link
Author

qortex commented Feb 13, 2019

Precision: debugging a barebone ruby script works ok (breakpoints are met).

@qortex
Copy link
Author

qortex commented Feb 13, 2019

Tried lots of different things but can't get it to work.
I followed again all steps on https://github.com/rubyide/vscode-ruby/wiki/1.-Debugger-Installation and following sections, but it doesn't stop on breakpoints, just hangs.

I use this new config following the guide:

{
  "name": "Rails server",
  "type": "Ruby",
  "request": "launch",
  "program": "/home/mic/.rbenv/versions/2.6.1/bin/rails",
  "cwd": "${workspaceRoot}",
  "showDebuggerOutput": true,
  "args": [
    "server"
  ]
}

I updated debase & ruby-debug-ide, now Fast Debugger (ruby-debug-ide 0.7.0.beta7, debase 0.2.3.beta5, file filtering is supported) listens on 127.0.0.1:1234 shows up in debug console. But debugger returns immediately, not launching a debug session. I can't see what error is met. Is there a log somewhere I could check?

In a barebone console, doing /home/mic/.rbenv/versions/2.6.1/bin/rails server from workspace root dir works well.

Can't really see where to go from there. Any pointer?

@qortex
Copy link
Author

qortex commented Feb 13, 2019

Ok, actually I realize that the issue is that the debugger does not attach to the process.

If I run rdebug-ide -- /home/mic/.rbenv/versions/2.6.1/bin/rails, and then try to attach the debugger, the debugger returns immediately without an error -- but I can see something happens because rdebug-ide actually launches the server at that time.

When using rdebug-ide -- bin/rails, I have the situation I described earlier (hangs if breakpoint is present before launching debugger, ignores breakpoints otherwise).

Can't think of a way to debug that. Any hint?

@qortex
Copy link
Author

qortex commented Feb 13, 2019

Tried to disable SPRING as stated in this thread ruby-debug/ruby-debug-ide#152

But with no luck either.

It really seems that when using the bin/rails version, it works but attaches to the wrong process. Thus, the breakpoint is hit but VS does not show the proper context.

If I hit "PAUSE" when it hangs, it stops in the Puma code (the webserver). So I think the debugger attaches to the Puma process instead of the worker thread.

Is it possible to check / force the behavior?

@wingrunr21
Copy link
Collaborator

Dup of #316

Sorry, I haven't focused on the debugger at all. It's coming...

@tillkolter
Copy link

@MicMicMon

I was struggling with the same issue on my machine. RDebug on the command line was not starting the rails server unless I did Ctrl+C once.

My colleague right next to me, who jumped into the project a few days later with a fresh installation of VSCode (we are both just on-boarding for a Ruby project coming from other IDE backgrounds) was not facing any issues and could debug from his first launch. I already had given up, but I couldn't accept that it was working for him and not for me, we were both running on Docker with same env variables, so in theory the basic project setup or any kind version mess didn't seem to be a problem.

The attached process and the debugger seemed to be connected, because killing the attached process would kill the debugger process.

My last resort was Wireshark to see what was going on the TCP networking level. Finally I had my Heurika moment. The attached IDE debug process was sending breakpoint positions to the debugger server process, including breakpoints from other projects. I removed all breakpoints and restarted the process and click – the server starts and I was able to break in my code.

Hope this helps anyone setting up his debugger and also @wingrunr21 to make the debug attaching more robust.

@wingrunr21
Copy link
Collaborator

@tillkolter thanks for this information. When you say "breakpoints from other projects", do you mean:

  1. breakpoints from projects open in other VSCode windows
  2. breakpoints from projects in different workspace roots
  3. breakpoints from projects that were opened in the past but are no longer open

Thanks!

@tillkolter
Copy link

@wingrunr21
In my initial case, I could fix it by removing old breakpoints from a project which was not longer open, but while I was just trying to find a minimum example to give you a more precise answer, I found out that the problematic constellation in my case was something different.

It was never a matter of location of the breakpoints, it was a matter of being disabled (my old spurious breakpoints had been disabled)

As soon as there is at least one breakpoint in the list, which is disabled, the debugged process is not starting, no matter if the breakpoint refers to a file within the project or not. As soon as I re-enabled all breakpoints, the process starts just fine.

Hope this helps.

@qortex
Copy link
Author

qortex commented May 6, 2019

Thanks for the tip @tillkolter !

Unfortunately, it still doesn't work for me :(
The debugger halts the process (I can see that because the output hangs in the middle of the response rails server generation) but VSCode never puts me in debugging context as expected.
:'(

@jonmchan
Copy link

jonmchan commented May 11, 2019

For everyone's info, there is a bug with the debugger and rails5. The gem bootsnap causes the breakpoints to not work (see https://youtrack.jetbrains.com/issue/RUBY-20684). If you can get the VSCode debugger to start and properly connect to the rdebug-ide process (you can run rdebug-ide -d to help verify this), then there isn't any issue with VSCode Ruby extension. The trick lies in fixing the debugger.

When you have -d running, set a breakpoint and verify that rdebug-ide is receiving it properly. You'll see the following immediately when you startup if the breakpoint is set before you launch:

75: Starting control thread
75: Processing in control: break /usr/src/app/config/application.rb:11

I have setup a RAILS_DEBUG environment flag that disables a lot of these optimizations to get the debugger working. The flag currently disables multiple workers in puma and disables loading bootsnap in config/boot.rb. That has gotten my setup working. Good luck for everyone else trying to get this working!

@minkir014
Copy link

Thanks for you help @jonmchan.

@qortex
Copy link
Author

qortex commented May 14, 2019

Thanks for your help @jonmchan
Unfortunately, disabling bootsnap and multiple workers didn't help. Debugger still stops the process, but VSCode does not jump to the line, showing context (I can just see the other threads running).

Didn't understand your rdebug-ide -d, could you elaborate?

What versions of ruby, ruby-debug-ide and debase do you use?

@minkir014
Copy link

Run rdebug-ide-d commnd and set a breakpoints. So you must see it in the terminal that it will break in the line number.

@qortex
Copy link
Author

qortex commented May 14, 2019

Don't know how to do that. What's your config file in VSCode? Is there a command to give the -d parameter to the spawned debugger?

Sorry, I'm not familiar with this setup :\

@aparmar
Copy link

aparmar commented Aug 6, 2019

Had the same issue. @tillkolter your method worked for me. Clicking "remove all breakpoints", and starting the debug process again worked for me! Now I can add new breakpoints as needed.

@Dearest
Copy link

Dearest commented Sep 26, 2019

I removed all breakpoints and restarted the process and click – the server starts and I was able to break in my code.

this is the point, I removed all breakpoints, and then I can use debugger

@joshianiket22
Copy link

Tried to disable SPRING as stated in this thread ruby-debug/ruby-debug-ide#152

But with no luck either.

It really seems that when using the bin/rails version, it works but attaches to the wrong process. Thus, the breakpoint is hit but VS does not show the proper context.

If I hit "PAUSE" when it hangs, it stops in the Puma code (the webserver). So I think the debugger attaches to the Puma process instead of the worker thread.

Is it possible to check / force the behavior?

Hi @MicMicMon
Were you able to get this working?

@qortex
Copy link
Author

qortex commented Nov 7, 2019

Hi @MicMicMon
Were you able to get this working?

Nope, unfortunately :( Quit trying after a while, I'm totally blind on how it works because I don't know those debug technologies.

I'm trying to switch to Windows & WSL / VSCode right now, I will give it another shot with this setup.

@jonmchan
Copy link

jonmchan commented Nov 7, 2019

The fix to that is to start puma in single thread mode.

export the following variables specifically:

WEB_CONCURRENCY=0 and RAILS_MAX_THREADS=1

https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#config

@qortex
Copy link
Author

qortex commented Nov 7, 2019

The fix to that is to start puma in single thread mode.

I remember trying that at the time but it didn't work either.

@jonmchan
Copy link

jonmchan commented Nov 7, 2019

I'm sorry, it wasn't 1, it was 0. Here is my exact start script:

#!/bin/bash
echo "running start-dev"

set -e


bundle install

#yarn install

echo "Running migrations..."
bundle exec rake db:create db:migrate
RAILS_ENV=test bundle exec rake db:create db:migrate

echo "Done running migrations..."

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

if [ "$RAILS_DEBUG" == "true" ]; then
  WEB_CONCURRENCY=0 RUBYLIB="" rdebug-ide --port 1234 --host 0.0.0.0 --dispatcher-port 26162 -- bin/rails s -b 0.0.0.0
else
  bin/rails s -b 0.0.0.0
fi

This script works for me to do debugging.

@joshianiket22
Copy link

The fix to that is to start puma in single thread mode.

export the following variables specifically:

WEB_CONCURRENCY=0 and RAILS_MAX_THREADS=1

https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#config

@jonmchan This worked for me. Thanks a lot.

@jonmchan
Copy link

jonmchan commented Nov 9, 2019

If i recall correctly, WEB_CONCURRENCY=1 doesn't work because puma ends up spawning one worker thread and keeps a separate master thread. Setting WEB_CONCURRENCY=0 makes puma not spawn any additional threads as far as I remember, but it's been a little since i researched into it.

@apinstein
Copy link

Using rdebug-ide -d I was able to debug my issue with using VSCode <> Dockerized ruby. I hope the answer I found will help others.

It was very simple and didn't have to do with stray leftover breakpoints, or threads, or concurrency.

Most of the tutorials for this tell you to configure your launch.json as:

            "remoteWorkspaceRoot": "${workspaceRoot}",
            "cwd": "${workspaceRoot}",

However, this won't work unless your Docker filesystem has the same shape as the local filesystem. You will see that it used my Mac filesystem:

pete             | Fast Debugger (ruby-debug-ide 0.7.0, debase 0.2.4.1, file filtering is supported) listens on 0.0.0.0:1234
pete             | Connected from 172.20.0.1
pete             | 7: Starting control thread
pete             | 7: Processing in control: break /Users/apinstein/dev/sidx-local-dev/pete/app/controllers/application_controller.rb:10
pete             | 7: <breakpointAdded no="1" location="/Users/apinstein/dev/sidx-local-dev/pete/app/controllers/application_controller.rb:10"/>

cwd is for the local side (with VSCode)
remoteWorkspaceRoot needs to be the path to your app in the Docker container.

Once I fixed this, it set the breakpoint on the proper path for what the rails server sees, and then my breakpoints started working.

pete             | Fast Debugger (ruby-debug-ide 0.7.0, debase 0.2.4.1, file filtering is supported) listens on 0.0.0.0:1234
pete             | Connected from 172.20.0.1
pete             | 7: Starting control thread
pete             | 7: Processing in control: break /usr/app/app/controllers/application_controller.rb:10
pete             | 7: <breakpointAdded no="1" location="/usr/app/app/controllers/application_controller.rb:10"/>

Hope this helps!

@tgmerritt
Copy link

tgmerritt commented Jul 3, 2020

Here is a working launch.json for me:

    "configurations": [
        {
            "name": "Rails server",
            "type": "Ruby",
            "request": "launch",
            "cwd": "${workspaceRoot}",
            "useBundler": true,
            "pathToBundler": "/Users/tyler/.rbenv/shims/bundle",
            "pathToRDebugIDE": "/Users/tyler/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2",
            "program": "${workspaceRoot}/bin/rails",
            "showDebuggerOutput": true,
            "args": [
                "server",
            ],
            "env": { *your ENV VARS go here*}
        }
     ]

You can grab your absolute path to ruby-debug-ide with bundle info ruby-debug-ide and the bundler with which bundler

It wouldn't work for me with the absolute path to the bundler gem (basically a path similar to the ruby-debug-ide path above - don't use that, use the shim or whatever RVM calls it)

Was having a monstrous time getting this to work like everyone else here - but this is the working configuration in my case.

I also manually installed rdebug-ide and debase gems - meaning I gem install ruby-debug-ide and gem install debase within the project folder.

https://lankydan.dev/2017/05/12/debugging-a-rails-server-in-visual-studio-code

I absolutely had to set WEB_CONCURRENCY to 0 and MAX_THREADS to 1

These are set in my puma.rb config file - they can be set other ways as other posters have commented. But don't forget this.

@bessfernandez
Copy link

Thanks @tgmerritt - this was the only way for me to get this to work. Here's a little more of my config below with all the env settings if it's helpful for anyone:

In my .env file set:

WEB_CONCURRENCY=0
RAILS_MAX_THREADS=1

And my launch.json looked similar to this:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Rails server",
      "type": "Ruby",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "program": "${workspaceRoot}/bin/rails",
      "showDebuggerOutput": true,
      // need to set env most likely below to get rails to attach to debugger properly
      // generate via: https://gist.github.com/alif-bae/dfe8c6612d5b42dd5b5be8cefdd4a0c7
      "env": {
        "PATH": "",
        "GEM_HOME": "",
        "GEM_PATH": "",
        "RUBY_VERSION": ""
      },
      "args": ["server"]
    }
  ]
}

@zephyrpathsofglory
Copy link

zephyrpathsofglory commented Sep 28, 2020

The fix to that is to start puma in single thread mode.
export the following variables specifically:
WEB_CONCURRENCY=0 and RAILS_MAX_THREADS=1
https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#config

@jonmchan This worked for me. Thanks a lot.

This worked for me too. Thanks a lot. Tips: do not forget to set the database pool to enough value to avoid

The fix to that is to start puma in single thread mode.

export the following variables specifically:

WEB_CONCURRENCY=0 and RAILS_MAX_THREADS=1

https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#config

It works for me. Thanks a lot. BTW, do not forget to assign enough database pool in database.yml file with pool: x for your environment to avoid ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)

@trevorbye
Copy link

I feel like getting this to work properly was like summiting Everest... Ultimately @jonmchan solution worked for me, but I'll comment everything I did here and some of my configs to be super clear for everyone in the future who is ramping on rails for the first time:

  1. In config/boot.rb I commented out require 'bootsnap/setup'
  2. In config/puma.rb I made WEB_CONCURRENCY=0 and RAILS_MAX_THREADS=1. I originally tried adding these as environment variables but they weren't being picked up for some reason, so I just changed them manually in puma.rb. Ideally you should be able to get that to work with your .env file variables, though.
  3. Make sure you run rdebug-ide -d to verify that your breakpoints are recognized in the container env. My full start command in docker-compose.yml ends up being bundle exec rdebug-ide -d --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0

Some other things I ran into along the way, and misinformation I ran into, that I had to fix that may help people who are brand new:

  1. In your launch.json, remoteWorkspaceRoot needs to point to the app root in your docker container. For me (and I think most default setups will also be like this for Rails) I had to set remoteWorkspaceRoot to /usr/src/app.

  2. Some of the tutorials out there are inaccurate:

    • This tutorial shows usage of an override file for docker compose docker-compose.debug.yml. You can do it this way, but running docker-compose up won't pick this file up automatically unless it is named docker-compose.override.yml. So for this tutorial you actually have to run docker-compose -f docker-compose.yml -f docker-compose.debug.yml, otherwise your debug config won't make it in there.

    • Most tutorials I found were either vague or completely incorrect about exposing your debug port. Your docker-compose.yml should look like this. Notice how the defined debug port 1234 is exposed in the ports list correctly:

      command: bundle exec rdebug-ide -d --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0
      environment: *common-variables
      ports:
        - 3000:3000
        - 1234:1234
      

Hopefully this helps, good luck getting this to work (you're going to need it...)!

@jonmchan
Copy link

jonmchan commented Jul 8, 2021

@trevorbye could you try adding the environment variables to the docker-compose.yml file via the environment: section instead of .env? .env is utilized in docker-compose to set environment variables for docker/docker-compose, you still need to define those variables to be utilized for the container, it doesn't make it into the container by default when you set it in .env.

@harumhl
Copy link

harumhl commented Apr 6, 2022

gist.github.com/alif-bae/dfe8c6612d5b42dd5b5be8cefdd4a0c7

"https://gist.github.com/alif-bae/dfe8c6612d5b42dd5b5be8cefdd4a0c7" does not exist anymore, but "https://gist.github.com/alifbae/dfe8c6612d5b42dd5b5be8cefdd4a0c7" is, redirecting you to "https://stackoverflow.com/questions/51722136/how-do-you-run-and-debug-ruby-on-rails-from-visual-studio-code".

PATH comes from your env var (e.g. echo $PATH)

According to https://stackoverflow.com/a/60012122,
GEM_PATH and GEM_HOME should come from running gem env

p.s. I still haven't gotten it to work tho

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

No branches or pull requests