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

Infinite loop #158

Open
ldodds opened this issue Aug 13, 2021 · 7 comments
Open

Infinite loop #158

ldodds opened this issue Aug 13, 2021 · 7 comments

Comments

@ldodds
Copy link

ldodds commented Aug 13, 2021

A Rails app I'm working on occasionally hangs, with the process becoming unresponsive and having to be killed.

We've also seen the same issue within the rails console and command-line scripts. In these cases a Ctrl-C causes the execution to either continue or end. But within the rails app we have to kill the process. We've removed some exception logging which was triggering the issue.

Using gdb and some manual testing, I've managed to identify that the issue is triggered whenever there is a NoMethodError generated by a call to an object and we are logging the exception message.

The gdb stack trace showed that a thread seems to be repeatedly calling methods in Correctable. When I remove the call to super.dup in to_s, to supply a hard-coded value instead, the issue went away.

We're currently on ruby-2.6.5 and Did You Mean 1.3.0.

I've tried upgrading to Did You Mean 1.5.0 but this doesn't seem to fix the issue. I also hit build/bundler issues similar to these which I've not been able to fully resolve.

We're looking to upgrade to newer ruby but I'm not sure if that will resolve the underlying problem as I gather its using version 1.5.0, but it might avoid the travis issues.

I've also been trying to disable the gem completely for the moment but setting RUBYOPT='--disable-did_you_mean' when running bundle exec rails s doesn't seem to work.

Any advice on other things I can try to either identify the cause or disable the gem?

@yuki24
Copy link
Member

yuki24 commented Aug 13, 2021

Do you have a code snippet that replicates the issue? It's hard to investigate without code examples. Keep in mind that if you rescue Exception it will also rescue SignalException and Interrupt and the process wouldn't be able to handle signals as intended.

@ldodds
Copy link
Author

ldodds commented Aug 24, 2021

I'll attempt to create a small test case, but may take me a little while to do that.

meinac added a commit to meinac/grape-entity that referenced this issue Aug 25, 2021
Calling `NameError#message` causes the `did_you_mean` library to endup
being in an infinite loop(Probabaly raises `SystemStackError` at some
point though).

Related to ruby/did_you_mean#158
@meinac
Copy link

meinac commented Aug 26, 2021

We are bitten by a similar problem exists in the grape-entity gem. I've already proposed a solution for it here: ruby-grape/grape-entity#355.

The problem is, #to_s and #message methods(name_err_mesg_to_str) of the NameError call the rb_inspect(based on the object type) and if the #inspect raises NameError, then it introduces an infinite loop.

The following snippet demonstrates the issue;

class Foo
  def bar
    zoo_1
  rescue => e
    raise e.class, e.message
  end

  def zoo
    true
  end

  def inspect
    bar
  end
end

Foo.new.bar

I think adding a warning to the documentation of the Kernel#inspect method would be nice.

meinac added a commit to meinac/ruby that referenced this issue Aug 26, 2021
@ldodds
Copy link
Author

ldodds commented Aug 26, 2021

Based on @meinac comments and some further testing I'm not sure that the issue is with did you mean and instead related to timing and errors with #to_s/#inspect.

@yuki24 if I comment out this line in the did you mean gem, then I assume it wont ever be activated for a NoMethodError?

  correct_error NoMethodError, MethodNameChecker

If so, then our problem is elsewhere and I can close this bug.

@ldodds
Copy link
Author

ldodds commented Aug 26, 2021

Our issue ended up not being with did you mean. The comments from @meinac were enough to track down our error which was actually due to issues with #to_s/#inspect calls.

We have a large data structure that was being held as a member variable of an object. Attempting to dump that via to_s or inspect is significantly slow. We don't do that normally.

Logging a NoMethodError from an object (in this case a Rails controller) that held an indirect reference to one of these structures caused the exception handling to dump those objects as part of calling #inspect somewhere. We've implemented #inspect on the relevant object to avoid logging the internals of the data structure and this fixes the problem. No further blocks which were presenting themselves as stuck processes.

I'm not sure whether there is a still an infinite loop issue as @meinac reports, so will leave this up to maintainer to close. But my original issue is resolved. Sorry for the noise!

@meinac
Copy link

meinac commented Aug 26, 2021

Thanks for double checking @ldodds. As you've mentioned, this is a problem with Ruby and not did_you_mean.

I am planning to propose a solution for Ruby like this or at least a warning message for the Kernel#inspect documentation. WDYT @yuki24?

LeFnord pushed a commit to ruby-grape/grape-entity that referenced this issue Aug 26, 2021
)

* Fix infinite loop problem with the `NameError`s in block exposures

Calling `NameError#message` causes the `did_you_mean` library to endup
being in an infinite loop(Probabaly raises `SystemStackError` at some
point though).

Related to ruby/did_you_mean#158

* Fix rubocop cop violations
@vakuum
Copy link

vakuum commented Nov 24, 2022

@ldodds: Does this commit rails/rails@080edb4 in Rails 6.1 solve the problem?

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

No branches or pull requests

4 participants