Puma 2.0.1 right now have a socket leak problem. It leaks socket/fd when it's restarted.
This application is a minimum set to show how puma leaks its sockets on restart. Same thing should happen on file descriptors.
First, this program tries to connect to a MySQL server, so please get one or some. Write the MySQL connection information to config.ru, such like
CONN = {
:host = "localhost",
:user = "user",
:password = "password"
}
and run:
$ bundle install --path=.bundle/gems --binstubs=.bundle/bin
don't forget the binstubs option.
and then run puma by:
$ bundle exec puma
or:
$ bundle exec puma --daemon
Access http://localhost:9292/
to see how many sockets are opened.
Access http://localhost:9292/reload
to send USR2 to the process.
When starting, the application simply opens a MySQL connection by using mysql2
gem.
Connection is kept in a class variable.
By accessing the server, you will see the sockets opened. This information is taken from /proc filesystem, so this application only works on Linux with procfs mounted (or those compatible to it).
Accessing to /reload
will send -USR2
to the server process itself.
You will be seeing the sockets increasing than before.
Puma server implements restart
by exec
-ing its process into a new one.
On exec
, file descriptors are not wasted by default.
If you want it wasted, you must set close-on-exec
on the file descriptor.
Ruby provides us an easy way to close the file descriptors (those higher than 0,1,2) when exec-ing,
by giving an option :close_others
to Kernel#exec
.
In ruby 2.0.0 or higher, file descriptors are created with close-on-exec
flag by default.
Therefore, this problem doesn't appear on ruby 2.0.0 or later.