Method: PG::Connection#socket_io

Defined in:
ext/pg_connection.c

#socket_ioObject

Fetch an IO object created from the Connection’s underlying socket. This object can be used per socket_io.wait_readable, socket_io.wait_writable or for IO.select to wait for events while running asynchronous API calls. IO#wait_*able is is Fiber.scheduler compatible in contrast to IO.select.

The IO object can change while the connection is established, but is memorized afterwards. So be sure not to cache the IO object, but repeat calling conn.socket_io instead.

Using this method also works on Windows in contrast to using #socket . It also avoids the problem of the underlying connection being closed by Ruby when an IO created using IO.for_fd(conn.socket) goes out of scope.



936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
# File 'ext/pg_connection.c', line 936

static VALUE
pgconn_socket_io(VALUE self)
{
	int sd;
	int ruby_sd;
	t_pg_connection *this = pg_get_connection_safe( self );
	VALUE cSocket;
	VALUE socket_io = this->socket_io;

	if ( !RTEST(socket_io) ) {
		if( (sd = PQsocket(this->pgconn)) < 0){
			pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
		}

		#ifdef _WIN32
			ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
			if( ruby_sd == -1 )
				pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");

			this->ruby_sd = ruby_sd;
		#else
			ruby_sd = sd;
		#endif

		cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
		socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));

		/* Disable autoclose feature */
		rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );

		RB_OBJ_WRITE(self, &this->socket_io, socket_io);
	}

	return socket_io;
}