NoMethodError: undefined method `name' for nil:NilClass
sj26 opened this issue · comments
I've been getting some odd errors when starting Puma using gel:
Traceback (most recent call last):
20: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/bin/puma-wild:31:in `<main>'
19: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cli.rb:78:in `run'
18: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/launcher.rb:184:in `run'
17: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:466:in `run'
16: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:133:in `spawn_workers'
15: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:133:in `times'
14: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:137:in `block in spawn_workers'
13: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:137:in `fork'
12: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:137:in `block (2 levels) in spawn_workers'
11: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/cluster.rb:273:in `worker'
10: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/runner.rb:162:in `start_server'
9: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/runner.rb:155:in `app'
8: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/configuration.rb:243:in `app'
7: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/configuration.rb:318:in `load_rackup'
6: from /Users/sj26/.local/gel/2.6.0/gems/puma-3.12.0/lib/puma/configuration.rb:305:in `rack_builder'
5: from /usr/local/Cellar/gel/0.3.0/lib/gel/compatibility/rubygems.rb:197:in `require'
4: from /usr/local/Cellar/gel/0.3.0/lib/gel/environment.rb:581:in `resolve_gem_path'
3: from /usr/local/Cellar/gel/0.3.0/lib/gel/locked_store.rb:87:in `gems_for_lib'
2: from /usr/local/Cellar/gel/0.3.0/lib/gel/locked_store.rb:87:in `each'
1: from /usr/local/Cellar/gel/0.3.0/lib/gel/locked_store.rb:87:in `block in gems_for_lib'
/usr/local/Cellar/gel/0.3.0/lib/gel/environment.rb:583:in `block in resolve_gem_path': undefined method `name' for nil:NilClass (NoMethodError)
It's coming from here:
https://github.com/gel-rb/gel/blob/v0.3.0/lib/gel/environment.rb#L583
I added a pp(path: path, subdir: subdir) if gem.nil?
in there and got:
{:path=>"active_record/railtie", :subdir=>nil}
{:path=>"i18n", :subdir=>nil}
Then I ran it again and got:
{:path=>"active_support", :subdir=>nil}
{:path=>"i18n", :subdir=>nil}
It seems to change subtly on each invocation. Race condition?
Interestingly, I just got:
{{:path:path=>=>"rack", :subdir=>nil}
"rack", :subdir=>nil}
But I think that might be due to Puma starting some child processes.
Oh, I'm going to guess this is due to fork(). :-/
This was biting me again today, so I've been doing some digging.
These two lines seem to be in some sort of race condition:
Lines 44 to 52 in 1cf6653
The g
variable is being populated with an incomplete list of gems, then the followign libs_for_gems
block seems to yield entries where for a given name
there is no g[name]
. This can be verified by switching v = [g[name], subdir]
to v = [g.fetch(name), subdir]
This only occurs for me when starting puma in clustered mode with more than one worker. I'm guessing that multiple forks from the same parent process leave this in a bad state somehow, and causes incomplete data to be returned from the underlying Gel::Store
because the Gel::DB
isn't fully flushed before fork — that's the only way I can conceive of this getting into such an inconsistent state.
I seem to be using the SDBM implementation:
Gel::Environment.with_root_store { |store| store.instance_variable_get(:@stores)["ruby"].instance_variable_get(:@primary_db) }
=> #<Gel::DB::SDBM:0x00007fca87da9810 @root="~/.local/gel/ruby", @name="store", @sdbm=#<SDBM:0x00007fca87da97c0>, @transaction=nil, @monitor=#<Monitor:0x00007fca87da9798 @mon_mutex=#<Thread::Mutex:0x00007fca87da9748>, @mon_mutex_owner_object_id=70253919685580, @mon_owner=nil, @mon_count=0>>
Commenting out the SDBM implementation of Gel::DB and using the PStore fallback solves this issue for me.
I still get this issue today, and I think this is what led me to stop using gel last time I tried 😢
10:26:32 puma | /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/environment.rb:557:in `block in scan_for_path': undefined method `name' for nil:NilClass (NoMethodError)
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/locked_store.rb:87:in `block in gems_for_lib'
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/locked_store.rb:87:in `each'
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/locked_store.rb:87:in `gems_for_lib'
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/environment.rb:555:in `scan_for_path'
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/environment.rb:572:in `resolve_gem_path'
10:26:32 puma | from /opt/homebrew/Cellar/gel/HEAD-ae273ca_1/lib/gel/compatibility/rubygems.rb:251:in `require'
10:26:32 puma | from /Users/sj26/.local/gel/ruby/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `block in require'
10:26:32 puma | from /Users/sj26/.local/gel/ruby/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:299:in `load_dependency'
10:26:32 puma | from /Users/sj26/.local/gel/ruby/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `require'
10:26:32 puma | from /Users/sj26/.local/gel/git/omniauth-github-967d76979b6bf/lib/omniauth/strategies/github.rb:1:in `<top (required)>'
Commenting out the SDBM implementation of Gel::DB and using the PStore fallback solves this issue for me.
SDBM support has been dropped because it was removed from stdlib, so maybe this is better now?