Make pgconn_connect_poll close the socket prior to calling PQconnectPoll
Since PQconnectPoll can change the underlying socket and thus the file descriptor, closing the socket after can manifest a race condition where libpq has closed the socket and another thread has opened a socket with the recycled file descriptor. When the original socket is closed from Ruby, the VM will notify the new thread that the FD has closed (erroneously) resulting in an exception.
This is an exception I encountered in a production environment (C Ruby 3.3), somewhat sporadically It is quite misleading as the way this manifests is that the exception raises while waiting on the socket, so it seems as if connections are getting shared between threads.
The reason this happens is because when the IO object is closed on the Ruby side, the VM calls rb_notify_fd_close which in turn sends an exception to any threads waiting on the file descriptor. On the Ruby 2.x path does not have this problem as IO.select will return the exception array, although I believe the VM still calls close()
Make
pgconn_connect_poll
close the socket prior to callingPQconnectPoll
Since
PQconnectPoll
can change the underlying socket and thus the file descriptor, closing the socket after can manifest a race condition where libpq has closed the socket and another thread has opened a socket with the recycled file descriptor. When the original socket is closed from Ruby, the VM will notify the new thread that the FD has closed (erroneously) resulting in an exception.This is an exception I encountered in a production environment (C Ruby 3.3), somewhat sporadically It is quite misleading as the way this manifests is that the exception raises while waiting on the socket, so it seems as if connections are getting shared between threads.
The reason this happens is because when the IO object is closed on the Ruby side, the VM calls rb_notify_fd_close which in turn sends an exception to any threads waiting on the file descriptor. On the Ruby 2.x path does not have this problem as
IO.select
will return the exception array, although I believe the VM still callsclose()