truffleruby icon indicating copy to clipboard operation
truffleruby copied to clipboard

Exception expanding the "Globals" section in the VS Code debugger

Open nirvdrum opened this issue 3 years ago • 1 comments

I'm trying to debug a Rails application. I'm using the following launch configuration:

{
  // 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": [
    {
      "type": "graalvm",
      "request": "launch",
      "name": "Launch Ruby Script",
      "runtimeExecutable": "ruby",
      "program": "${workspaceFolder}/bin/rails",
      "args": ["server", "-p", "7089"],
      "console": "integratedTerminal",
      "cwd": "${workspaceFolder}",
      "outputCapture": "std",
      "protocol": "debugAdapter",
    },
  ]
}

I set a breakpoint in ApplicationController on a include line. It looks something like:

# frozen_string_literal: true
class ApplicationController < ActionController::Base
  include Authentication
  ...
end

While paused at the breakpoint on the include Authentication line, I expanded the "Globals" section in the "Variables" view. There's two sections labeled "Globals". I expanded the top-most one, which prints Ruby global variables. When I expanded it, the debugger/application crashed with:

truffleruby: an internal exception escaped out of the interpreter,
please report it to https://github.com/oracle/truffleruby/issues.

No such file or directory - -p (Errno::ENOENT) (com.oracle.truffle.api.debug.DebugException)
        from <ruby>.Kernel#raise(resource:/truffleruby/core/kernel.rb:692)
        from <ruby>.Errno.handle(resource:/truffleruby/core/errno.rb:48)
        from <ruby>.IO.sysopen(resource:/truffleruby/core/io.rb:889)
        from <ruby>.File#initialize(resource:/truffleruby/core/file.rb:1216)
        from <ruby>.IO.open(resource:/truffleruby/core/io.rb:665)
        from <ruby>.Truffle::ARGFClass#stream(resource:/truffleruby/core/argf.rb:550)
        from <ruby>.Truffle::ARGFClass#advance!(resource:/truffleruby/core/argf.rb:613)
        from <ruby>.Truffle::ARGFClass#filename(resource:/truffleruby/core/argf.rb:231)
        from <ruby>.block in <top (required)>(resource:/truffleruby/core/argf.rb:636)
        from <ruby>.<top (required)>((eval):1)
        from <ruby>.Binding#eval(resource:/truffleruby/core/binding.rb:13)
        from <ruby>.<class:ApplicationController>(Unknown:-1)
        from <ruby>.<top (required)>(application_controller.rb:2)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:27)
        from <ruby>.<module:InheritedResources>(base.rb:11)
        from <ruby>.<top (required)>(base.rb:1)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:27)
        from <ruby>.<module:ActiveAdmin>(authorization.rb:3)
        from <ruby>.<top (required)>(authorization.rb:2)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:35)
        from <ruby>.<top (required)>(base_controller.rb:2)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:35)
        from <ruby>.<module:ActiveAdmin>(action_builder.rb:3)
        from <ruby>.<top (required)>(action_builder.rb:2)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:35)
        from <ruby>.<top (required)>(resource_controller.rb:3)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.Kernel#require(kernel.rb:35)
        from <ruby>.block in <top (required)>(batch_actions.rb:8)
        from <ruby>.block in ActiveAdmin.wrap_block_for_active_support_notifications(active_admin.rb:116)
        from <ruby>.ActiveSupport::Notifications::Fanout::Subscribers::Timed#finish(fanout.rb:236)
        from <ruby>.block in ActiveSupport::Notifications::Fanout#finish(fanout.rb:76)
        from <ruby>.block in ActiveSupport::Notifications::Fanout#iterate_guarding_exceptions(fanout.rb:91)
        from <ruby>.Array#each((core):1)
        from <ruby>.ActiveSupport::Notifications::Fanout#iterate_guarding_exceptions(fanout.rb:90)
        from <ruby>.ActiveSupport::Notifications::Fanout#finish(fanout.rb:76)
        from <ruby>.ActiveSupport::Notifications::Instrumenter#finish_with_state(instrumenter.rb:49)
        from <ruby>.ActiveSupport::Notifications::Instrumenter#instrument(instrumenter.rb:30)
        from <ruby>.ActiveSupport::Notifications.instrument(notifications.rb:206)
        from <ruby>.ActiveAdmin::Application#load!(application.rb:115)
        from <ruby>.ActiveAdmin::Application#routes(application.rb:142)
        from <ruby>.#<Class:ActiveAdmin>#routes(/home/spin/.bundle/yo/gems/activeadmin-2.13.1/lib/active_admin.rb:1)
        from <ruby>.block in <top (required)>(routes.rb:205)
        from <ruby>.BasicObject#instance_exec((core):1)
        from <ruby>.ActionDispatch::Routing::RouteSet#eval_block(route_set.rb:428)
        from <ruby>.ActionDispatch::Routing::RouteSet#draw(route_set.rb:410)
        from <ruby>.<top (required)>(routes.rb:4)
        from <ruby>.Truffle::KernelOperations.load((core):1)
        from <ruby>.Kernel#load(resource:/truffleruby/core/kernel.rb:376)
        from <ruby>.block in Rails::Application::RoutesReloader#load_paths(routes_reloader.rb:50)
        from <ruby>.Array#each((core):1)
        from <ruby>.Rails::Application::RoutesReloader#load_paths(routes_reloader.rb:50)
        from <ruby>.Rails::Application::RoutesReloader#reload!(routes_reloader.rb:24)
        from <ruby>.block in Rails::Application::RoutesReloader#updater(routes_reloader.rb:38)
        from <ruby>.ActiveSupport::FileUpdateChecker#execute(file_update_checker.rb:83)
        from <ruby>.Rails::Application::RoutesReloader#execute(/home/spin/.bundle/yo/gems/railties-7.0.3.1/lib/rails/application/routes_reloader.rb:1)
        from <ruby>.block in <module:Finisher>(finisher.rb:158)
        from <ruby>.BasicObject#instance_exec((core):1)
        from <ruby>.Rails::Initializable::Initializer#run(initializable.rb:32)
        from <ruby>.block in Rails::Initializable#run_initializers(initializable.rb:61)
        from <ruby>.block in TSort.tsort_each(tsort.rb:228)
        from <ruby>.block (2 levels) in TSort.each_strongly_connected_component(tsort.rb:350)
        from <ruby>.TSort.each_strongly_connected_component_from(tsort.rb:431)
        from <ruby>.block in TSort.each_strongly_connected_component(tsort.rb:349)
        from <ruby>.Array#each((core):1)
        from <ruby>.TSort.each_strongly_connected_component(tsort.rb:347)
        from <ruby>.TSort.tsort_each(tsort.rb:226)
        from <ruby>.TSort#tsort_each(tsort.rb:205)
        from <ruby>.Rails::Initializable#run_initializers(initializable.rb:60)
        from <ruby>.Rails::Application#initialize!(application.rb:372)
        from <ruby>.<top (required)>(environment.rb:7)
        from <ruby>.Kernel#require_relative(resource:/truffleruby/core/kernel.rb:293)
        from <ruby>.<top (required)>(config.ru:3)
        from <ruby>.Rack::Builder.new_from_string(builder.rb:116)
        from <ruby>.Rack::Builder.load_file(builder.rb:105)
        from <ruby>.Rack::Builder.parse_file(builder.rb:66)
        from <ruby>.Rack::Server#build_app_and_options_from_config(server.rb:349)
        from <ruby>.Rack::Server#app(server.rb:249)
        from <ruby>.Rack::Server#wrapped_app(server.rb:422)
        from <ruby>.Rails::Server#log_to_stdout(server_command.rb:76)
        from <ruby>.Rails::Server#start(server_command.rb:36)
        from <ruby>.block in Rails::Command::ServerCommand#perform(server_command.rb:143)
        from <ruby>.Kernel#tap(resource:/truffleruby/core/kernel.rb:510)
        from <ruby>.Rails::Command::ServerCommand#perform(server_command.rb:134)
        from <ruby>.Thor::Command#run(command.rb:27)
        from <ruby>.Thor::Invocation#invoke_command(invocation.rb:127)
        from <ruby>.Thor.dispatch(thor.rb:392)
        from <ruby>.Rails::Command::Base.perform(base.rb:87)
        from <ruby>.Rails::Command.invoke(command.rb:48)
        from <ruby>.<top (required)>(commands.rb:18)
        from <ruby>.Kernel#gem_original_require(resource:/truffleruby/core/kernel.rb:234)
        from <ruby>.<main>(rails:5)
        from <ruby>.Truffle::Boot.main((core):1)
        from <ruby>.block in <top (required)>(main_boot_source:1)
/home/spin/src/github.com/yo/yo/app/controllers/application_controller.rb:2:in `<class:ApplicationController>'
        from /home/spin/src/github.com/yo/yo/app/controllers/application_controller.rb:2:in `<top (required)>'
        from bin/rails:5:in `<main>'
        ... <truncate here>

nirvdrum avatar Sep 08 '22 20:09 nirvdrum

The issue here is that $FILENAME is a preexisting global, which when read returns the same as ARGF.filename. And that also fails on CRuby in such a case:

$ ruby -ve 'p $FILENAME' -- arg1 arg2
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux]
-e:1:in `<main>': No such file or directory @ rb_sysopen - arg1 (Errno::ENOENT)

I think InteropLibrary#hasMemberReadSideEffects() is exactly for this case, so we need to override it and return true for globals which have a getter Proc.

eregon avatar Sep 09 '22 06:09 eregon