Skip to content

Remote debugging of rake test raises Errno::EADDRINUSE #368

Description

@suketa

Your environment

  • ruby -v: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
  • rdbg -v: rdbg 1.3.4

Describe the bug
remote debugging with rake test raises Errno::EADDRINUSE

To Reproduce
Rakefile:

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
  t.test_files = ['test_example.rb']
end

test_example.rb:

require 'minitest/autorun'

class TestExample < Minitest::Test
  def test_foo
    binding.break
    assert_equal(true, true)
  end
end

And run in console:

$ rdbg -O -p 12345 -c rake test

And connect from another console and type c:

$ rdbg -A 12345
[5, 14] in ~/.asdf/installs/ruby/3.0.2/bin/rake
     5| # The application 'rake' is installed as part of a gem, and
     6| # this file is here to facilitate running it.
     7| #
     8|
     9|
=>  10| version = ">= 0.a"
    11|
    12| str = ARGV.first
    13| if str
    14|   str = str.b[/\A_(.*)_\z/, 1]
=>#0    <main> at ~/.asdf/installs/ruby/3.0.2/bin/rake:10
(rdbg:remote) c    # continue command

Then Errno::EADDRINUSE was raised in server console.

$ rdbg -O -p 12345 -c rake test
DEBUGGER: Debugger can attach via TCP/IP (127.0.0.1:12345)
DEBUGGER: wait for debugger connection...
DEBUGGER: Connected.
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:131: warning: assigned but unused variable - r
DEBUGGER: wait for debugger connection...
#<Thread:0x0000562eb6c48160@DEBUGGER__::Server::reader /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:43 run> terminated with exception (report_on_exception is true):
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
["DEBUGGER Exception: /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/thread_client.rb:967",
 #<Errno::EADDRINUSE: Address already in use - bind(2) for 127.0.0.1:12345>,
 ["/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'"]]
#<Thread:0x0000562eb6c3ff60@DEBUGGER__::SESSION@server /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/session.rb:144 aborting> terminated with exception (report_on_exception is true):
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
rake aborted!
Command failed with status (1)

Tasks: TOP => test
(See full trace by running task with --trace)
DEBUGGER: Disconnected.

Expected behavior

Not raise Errno::EADDRINUSE and debugger stops at binding.break line in test_example.rb.

Activity

  1. changed the title [-]Remote debugging of `rake test` raises Errno::EADDRINUSE[/-] [+]Remote debugging of `rake test` raises `Errno::EADDRINUSE`[/+] on Nov 6, 2021
  2. ko1 commented on Nov 8, 2021

    @ko1
    Collaborator

    I'm not sure how the rake test invokes the test process, but I think the following scenario.

    (1) Running rake with debugg port == 12345
    (2) Create another process for the test (test worker) and tries to open the debug port 12345, but it's already opened at (1).

     6966 pts/0    S+     0:00 ruby /home/ko1/.rbenv/versions/2.7.3/bin/rake test
     6994 pts/0    S+     0:00 sh -c /home/ko1/.rbenv/versions/2.7.3/bin/ruby -w -I"lib" /home/ko1/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb "test_example.rb"
     6995 pts/0    Sl+    0:00 /home/ko1/.rbenv/versions/2.7.3/bin/ruby -w -Ilib /home/ko1/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb test_example.rb
    

    On my environment the ps log shows 2 ruby processes are created and confirms (2).

    Now I have no idea how to solve it... Hmm.

    Two possible solutions:

    (1) use port 0. It assigns free port randomly.
    (2) Disable debugger at the beginning of Rakefile (not implemented yet).

  3. ko1 commented on Nov 8, 2021

    @ko1
    Collaborator

    It is big change but

    (3) introduce remote proxy server for remote debuggees

    It seems orthodox method, but it needs a time.

  4. ko1 commented on Mar 25, 2022

    @ko1
    Collaborator

    Now I don't have a good solution on it.

  5. rubensa commented on Jul 21, 2022

    @rubensa

    Think I found a similar problem. See: connorshea/vscode-ruby-test-adapter#92 (comment)

  6. ko1 commented on Jul 27, 2022

    @ko1
    Collaborator

    Wow rdbg is used by another project ;p

  7. gerymate commented on Oct 8, 2024

    @gerymate
    Contributor

    I think using a port range for the debugger to try can be a good compromise. For example a port range can be reliably open on a container. I'd leave the task of deciding which debuggee is which to the user, it can be relative easily done based on the internal state of the debuggees.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions