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

Stackoverflow calling "super" from included module method #5272

Closed
dr-itz opened this Issue Aug 2, 2018 · 4 comments

Comments

Projects
None yet
2 participants
@dr-itz
Copy link
Contributor

commented Aug 2, 2018

Environment

  • JRuby 9.1.17.0 or 9.1.60.0
  • Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

Expected behavior

Calling super works in 9.1.x. It does in 9.2.0.0

Actual behaviour

In jruby/activerecord-jdbc-adapter the SQLite3Adapter is structured as follows:

module ArJdbc
  module Abstract
    module Core
      ...

      def translate_exception(exception, message)
        # what is expected to be called from "super" below
      end
    end
  end
end


module ArJdbc
  module SQLite3
    ...

    private

    def translate_exception(exception, message)
      # bunch of other cases, falls back to "super"
      super
    end
  end
end

module ActiveRecord::ConnectionAdapters
  class SQLite3Adapter < AbstractAdapter
    include ArJdbc::Abstract::Core
    include ArJdbc::SQLite3

    ...
  end
end

when translate_exception is called in ActiveRecord::ConnectionAdapters::SQLite3Adapter, the one from the ArJdbc::SQLite3 module is called as expected. When this in turn calls super, it ends up calling itself which gives a StackOverflowError. It's supposed to call the implementation from ArJdbc::Abstract::Core. Note: it's not limited to this methods, others are affected as well.

The relevant stack traces (cleaned up a bit for readability):

Ruby side:

...and so on
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477:in `translate_exception'
activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:722:in `translate_exception'
rails52/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:563:in `translate_exception_class'
rails52/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:582:in `block in log'
rails52/activesupport/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
rails52/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:569:in `log'
activerecord-jdbc-adapter/lib/arjdbc/abstract/database_statements.rb:65:in `execute'
rails52/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb:496:in `drop_table'
rails52/activerecord/test/cases/migration_test.rb:57:in `block in MigrationTest'
rails52/activerecord/test/cases/migration_test.rb:56:in `each'
rails52/activerecord/test/cases/migration_test.rb:56:in `block in MigrationTest'

Java side:

Java::JavaLang::StackOverflowError:
    org.joni.Matcher.forwardSearchRange(Matcher.java:131)
    org.joni.Matcher.searchInterruptible(Matcher.java:415)
    org.jruby.RubyRegexp$SearchMatchTask.run(RubyRegexp.java:269)
    org.jruby.RubyRegexp$SearchMatchTask.run(RubyRegexp.java:250)
    org.jruby.RubyThread.executeTask(RubyThread.java:1481)
    org.jruby.RubyRegexp.matcherSearch(RubyRegexp.java:233)
    org.jruby.RubyRegexp.search19(RubyRegexp.java:1232)
    org.jruby.RubyRegexp.search19(RubyRegexp.java:1178)
    org.jruby.RubyRegexp.eqq19(RubyRegexp.java:1088)
    org.jruby.RubyRegexp$INVOKER$i$1$0$eqq19.call(RubyRegexp$INVOKER$i$1$0$eqq19.gen)
    org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:153)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.invokeOther3:===(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:462)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:462)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0$__VARARGS__(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb)
    org.jruby.internal.runtime.methods.CompiledIRMethod.call(CompiledIRMethod.java:77)
    org.jruby.internal.runtime.methods.MixedModeIRMethod.call(MixedModeIRMethod.java:93)
    org.jruby.ir.runtime.IRRuntimeHelpers.unresolvedSuper(IRRuntimeHelpers.java:1042)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.invokeSuper16:-unknown-super-target-(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0$__VARARGS__(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb)
    org.jruby.internal.runtime.methods.CompiledIRMethod.call(CompiledIRMethod.java:77)
    org.jruby.internal.runtime.methods.MixedModeIRMethod.call(MixedModeIRMethod.java:93)
    org.jruby.ir.runtime.IRRuntimeHelpers.unresolvedSuper(IRRuntimeHelpers.java:1042)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.invokeSuper16:-unknown-super-target-(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477)
    activerecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb:477)
    Uctiverecord_minus_jdbc_minus_adapter.lib.arjdbc.sqlite3.adapter.RUBY$method$translate_exception$0$__VARARGS__(activerecord-jdbc-adapter/lib/arjdbc/sqlite3/adapter.rb)
	... and a ton more of these

Workaround

Moving the affected methods from the ArJdbc::SQLite3 module to the ActiveRecord::ConnectionAdapters::SQLite3Adapter class, super works as expected calling the implementation in ArJdbc::Abstract::Core.

Reproducer

A reduced version of this runs fine. Also, in ARJDBC the PostgreSQL adapter is structured the same and works fine. When running the SQLite3 adater on 9.2.0.0 it runs fine as well. Reproducer for the full thing:

  1. In activerecord-jdbc-adapter: prepare and build

    $ bundle
    $ rake jar
    
  2. Prepare env

    $ export RAILS=/path/to/full/rails52/
    
  3. Run one of the failing tests

    $ rake rails:test_sqlite3 TEST=test/cases/migration_test.rb
    
@enebo

This comment has been minimized.

Copy link
Member

commented Aug 2, 2018

@headius this looks super familiar right? Did we fix something with prepend or something on master that we did not cherry pick?

@dr-itz

This comment has been minimized.

Copy link
Contributor Author

commented Aug 6, 2018

prepend is exactly the cause. Looked a bit closer at the ancestors and found this:

ActiveRecord::ConnectionAdapters::SQLite3Adapter
ArJdbc::Abstract::TransactionSupport
ArJdbc::Abstract::StatementCache
ArJdbc::Abstract::DatabaseStatements
#<Module:0x1d269ed7>
ArJdbc::SQLite3
ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements
ActiveRecord::ConnectionAdapters::SQLite3::Quoting
ArJdbc::Abstract::Core
ActiveRecord::ConnectionAdapters::AbstractAdapter
ActiveRecord::ConnectionAdapters::Savepoints
ActiveRecord::ConnectionAdapters::QueryCache
ActiveRecord::ConnectionAdapters::DatabaseLimits
ActiveRecord::ConnectionAdapters::Quoting
#<Module:0x437ebf59>
ActiveRecord::ConnectionAdapters::DatabaseStatements
ActiveRecord::ConnectionAdapters::SchemaStatements
ActiveRecord::Migration::JoinTable
ActiveSupport::Callbacks
ActiveSupport::ToJsonWithActiveSupportEncoder
Object
Metaclass::ObjectMethods
Mocha::ObjectMethods
ActiveSupport::Dependencies::Loadable
ActiveSupport::Tryable
JSON::Ext::Generator::GeneratorMethods::Object
Kernel
BasicObject

That anonymous module right before ArJdbc::SQLite3 triggers the problem. It's inserted by Rails' deprecate and can be easily worked around:
jruby/activerecord-jdbc-adapter@3986274

@dr-itz

This comment has been minimized.

Copy link
Contributor Author

commented Aug 8, 2018

@enebo I guess it's 7ce8544 and 3cb5f89

@enebo

This comment has been minimized.

Copy link
Member

commented Aug 9, 2018

@dr-itz thanks for pointing that out. cherry-picked and all looks well. Only travising hitting a test I did not run locally could re-open this now.

@enebo enebo closed this Aug 9, 2018

@enebo enebo added this to the JRuby 9.2.1.0 milestone Nov 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.