digital-fabric / tipi

Tipi - the All-in-one Web Server for Ruby Apps
MIT License
244 stars 7 forks source link

Application freezes when trying to connect to Mongodb #33

Open StephanieSunshine opened 10 months ago

StephanieSunshine commented 10 months ago

Trying to setup a connection to a Mongo database, an application just hangs. If I take the connection line in question into irb or pry it works as expected. Strace points to something within io_uring.

Strace output:

clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x7ff2fa55c990, parent_tid=0x7ff2fa55c990, exit_signal=0, stack=0x7ff2fa35c000, stack_size=0x1fff80, tls=0x7ff2fa55c6c0} => {parent_tid=[47625]}, 88) = 47625
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 2, 0, 0, NULL, 8)     = 2
io_uring_enter(5, 0, 1, IORING_ENTER_GETEVENTS, NULL, 8) = 0
getpid()                                = 47614
futex(0x5596d2b2ce68, FUTEX_WAIT_BITSET_PRIVATE, 0, {tv_sec=97766, tv_nsec=523406835}, FUTEX_BITSET_MATCH_ANY) = 0
futex(0x5596d2b2cfd8, FUTEX_WAIT_PRIVATE, 2, NULL) = 0
futex(0x7ff2f4003ee8, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x5596d2b2cfd8, FUTEX_WAKE_PRIVATE, 1) = 0
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 1, 0, 0, NULL, 8)     = 1
io_uring_enter(5, 0, 1, IORING_ENTER_GETEVENTS, NULL, 8

server.rb

require 'logger'
require 'mongo'
require 'tipi'

opts = {
  reuse_addr:  true,
  dont_linger: true
}

L = Logger.new(STDOUT)

L.info 'Connecting to database'

# Offending line that hangs if uncommented 
#M = Mongo::Client.new(['node1.cloud:27017', 'node2.cloud:27017', 'node3.cloud:27017'], database: 'xxxxx', max_pool_size: 200, max_connecting: 10, read: { mode: :secondary_preferred })

L.info "pid: #{Process.pid}"
L.info 'Listening on port 12345...'

server = Tipi.route do |r|
  r.on 'get' do
    L.info 'route /get called'
    r.respond 'get'
  end

spin do
  Tipi.serve('0.0.0.0', 12345, opts, &server)
StephanieSunshine commented 10 months ago

Just to add to this, reducing the server.rb app to just the most basic test, the Mongo connect line does work.

bare.rb

require 'logger'
require 'mongo'
require 'pry'

L = Logger.new(STDOUT)
L.info 'Connecting to database'
M = Mongo::Client.new(['node1.cloud:27017', 'node2.cloud:27017', 'node3.cloud:27017'], database: 'xxxxx', max_pool_size: 200, max_connecting: 10, read: { mode: :secondary_preferred })
binding.pry