rails-sqlserver / tiny_tds

TinyTDS - Simple and fast FreeTDS bindings for Ruby using DB-Library.
Other
605 stars 191 forks source link

When connection fails, a hanging anonymous inode is left open in the system #528

Open b-nik opened 1 year ago

b-nik commented 1 year ago

Environment

Tested on: Ubuntu 18.04 with freetds v.1.00.110 / TDS Version: 7.4 Ubuntu 20.04 with freetds v.1.2.12 / TDS Version: auto

Affected Gem Versions: all? (tested with 0.1.0, 0.7.0, 1.3.0, 2.1.2, 2.1.5)

Description

When connection fails, a hanging anonymous inode is left open in the system.

How to reproduce:

  1. Run Rails console - take note of the process pid.
  2. On a separate terminal run: lsof -p _PIDHERE | grep eventfd - nothing should appear
  3. In Rails console run TinyTds::Client.new(host: "localhost") or anything that would fail
  4. On a separate terminal run: lsof -p _PIDHERE | grep eventfd - you'll see an inode entry.
  5. Keep running step 3 and 4 and you'll see inode entries will keep appearing, never closing.
  6. Close the terminal - all inodes are now freed.
  7. If on step 3 you run a TinyTds::Client.new that succeeds the inode entry only remains until you close the connection. If the connection fails, there's no way to free the resource since TinyTds::Client.new returns an exception.

On a production environment TinyTds ran in a sidekiq job - some times it would fail to connect, and eventually that left so many open inodes that sidekiq would fail most jobs with a "too many open files error".