puma: Errno::EBADF on restart via pumactl

Steps to reproduce

  1. Restart Puma with ~/.rvm/bin/rvm default do bundle exec pumactl -S /var/www/app/shared/tmp/pids/puma.state -F /var/www/app/shared/puma.rb restart

Expected behavior

To restart puma normally without 502 error.

Actual behavior

=== puma startup: 2019-09-11 08:12:49 +0000 ===
/var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/binder.rb:405:in `for_fd': Bad file descriptor - fstat(2) (Errno::EBADF)
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/binder.rb:405:in `inherit_unix_listener'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/binder.rb:122:in `block in parse'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/binder.rb:97:in `each'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/binder.rb:97:in `parse'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/runner.rb:154:in `load_and_bind'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/single.rb:98:in `run'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/launcher.rb:188:in `run'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/lib/puma/cli.rb:80:in `run'
        from /var/www/app/shared/bundle/ruby/2.6.0/gems/puma-4.1.1/bin/puma:10:in `<top (required)>'
        from /var/www/app/shared/bundle/ruby/2.6.0/bin/puma:23:in `load'
        from /var/www/app/shared/bundle/ruby/2.6.0/bin/puma:23:in `<main>'
        from /var/www/app/shared/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `eval'
        from /var/www/app/shared/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `<main>'

System configuration

Ruby version: 2.6.4-p104 Rails version: 5.2.3 Puma version: 4.1.1

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 17 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Just like mentioned in the Socket Activation section of the systemd documentation, changing the restart_command to "bundle exec --keep-file-descriptors puma" solved the problem.

Maybe a link to this section in the restart documentation might help people like me, who read the restart documentation looking for a solution but missed the socket activation documentation 🤔.

Everything seems to work if I change my puma.rb file to remove the line saying:

restart_command "bundle exec puma"

No idea why, though. In case it’s relevant, I’m using RVM, and I start puma using:

bundle exec puma -C shared/puma.rb -e production -d

@javierm My problem was that I was running systemctl --user puma.service (storing service in the $HOME/~config/systemd/) which cause me a lot of issues. After moving puma service to /etc/systemd/system everything started working fine.

@majksner Did you figure it out in the end? I’m getting the same error with Ruby 2.4. I’ve tried puma 4.2.1, puma 4.0.1 and puma 3.12.1, with the same results:

$ bundle exec pumactl -S /home/deploy/consul/shared/tmp/pids/puma.state -F /home/deploy/consul/shared/puma.rb restart
Command restart sent success

The log says pretty much the same thing:

=== puma startup: 2019-10-14 00:58:27 +0200 ===
=== puma startup: 2019-10-14 01:02:07 +0200 ===
/home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/binder.rb:407:in `for_fd': Bad file descriptor - fstat(2) (Errno::EBADF)
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/binder.rb:407:in `inherit_unix_listener'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/binder.rb:124:in `block in parse'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/binder.rb:89:in `each'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/binder.rb:89:in `parse'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/runner.rb:154:in `load_and_bind'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/single.rb:98:in `run'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/launcher.rb:172:in `run'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/lib/puma/cli.rb:80:in `run'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/gems/puma-4.2.1/bin/puma:10:in `<top (required)>'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/bin/puma:23:in `load'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/bin/puma:23:in `<main>'
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/bin/ruby_executable_hooks:24:in `eval
        from /home/deploy/consul/shared/bundle/ruby/2.4.0/bin/ruby_executable_hooks:24:in `<main>'

Here’s my puma.rb file:

#!/usr/bin/env puma

app_dir = "/home/deploy/consul/current"
shared_dir = "/home/deploy/consul/shared"

directory app_dir
rackup "#{app_dir}/config.ru"
environment "production"

tag ""

pidfile "#{shared_dir}/tmp/pids/puma.pid"
state_path "#{shared_dir}/tmp/pids/puma.state"
stdout_redirect "#{shared_dir}/log/puma_access.log", "#{shared_dir}/log/puma_error.log", true

threads 0,16

bind "unix://#{shared_dir}/tmp/sockets/puma.sock"

workers 0

restart_command "bundle exec puma"

prune_bundler

on_restart do
  puts "Refreshing Gemfile"
  ENV["BUNDLE_GEMFILE"] = ""
end

And the socket seems to have the right permissions:

$ ls -l /home/deploy/consul/shared/tmp/sockets/
total 0
srwxrwxrwx 1 deploy wheel 0 Oct 14 01:39 puma.sock

The application was generated running CONSUL’s installer, which uses Ansible, on the secrets branch, on a server with a fresh Ubuntu 16.04 installation: https://github.com/consul/installer/tree/secrets

One thing to note: trying our installer with the master branch and unicorn and then switching to puma using capistrano3-puma worked alright the time I tried.

By the way, someone else seems to get a similar error with Ruby 2.5: seuros/capistrano-puma#286