Re: libpq should not look up all host addresses at once
| От | Tom Lane |
|---|---|
| Тема | Re: libpq should not look up all host addresses at once |
| Дата | |
| Msg-id | 27728.1534189594@sss.pgh.pa.us обсуждение исходный текст |
| Ответ на | Re: libpq should not look up all host addresses at once (Fabien COELHO <coelho@cri.ensmp.fr>) |
| Ответы |
Re: libpq should not look up all host addresses at once
|
| Список | pgsql-hackers |
Fabien COELHO <coelho@cri.ensmp.fr> writes:
> Patch compiles, global "make check" ok, although I'm unsure whether the
> feature is actually tested somewhere. I think not:-(
Yeah, it's hard to test this stuff without either opening up security
hazards or making unwarranted assumptions about the local network setup.
I think that the standard regression tests only use Unix-socket
communication (except on Windows) for exactly that reason, and that makes
it hard to do anything much about regression-testing this feature.
> As you noted in another message, a small doc update should be needed.
Check. Proposed doc patch attached. (Only the last hunk is actually
specific to this patch, the rest is cleanup that I noticed while looking
around for possibly-relevant text.)
> I'd consider wrapping some of the logic. I'd check the port first, then
> move the host resolution stuff into a function.
Don't really see the value of either ...
regards, tom lane
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 80e55f5..7c150f3 100644
*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
*************** PostgresPollingStatusType PQconnectPoll(
*** 303,311 ****
<itemizedlist>
<listitem>
<para>
! The <literal>hostaddr</literal> and <literal>host</literal> parameters are used appropriately to ensure
that
! name and reverse name queries are not made. See the documentation of
! these parameters in <xref linkend="libpq-paramkeywords"/> for details.
</para>
</listitem>
--- 303,311 ----
<itemizedlist>
<listitem>
<para>
! The <literal>hostaddr</literal> parameter must be used appropriately
! to prevent DNS queries from being made. See the documentation of
! this parameter in <xref linkend="libpq-paramkeywords"/> for details.
</para>
</listitem>
*************** PostgresPollingStatusType PQconnectPoll(
*** 318,324 ****
<listitem>
<para>
! You ensure that the socket is in the appropriate state
before calling <function>PQconnectPoll</function>, as described below.
</para>
</listitem>
--- 318,324 ----
<listitem>
<para>
! You must ensure that the socket is in the appropriate state
before calling <function>PQconnectPoll</function>, as described below.
</para>
</listitem>
*************** PostgresPollingStatusType PQconnectPoll(
*** 326,349 ****
</para>
<para>
! Note: use of <function>PQconnectStartParams</function> is analogous to
! <function>PQconnectStart</function> shown below.
! </para>
!
! <para>
! To begin a nonblocking connection request, call <literal>conn =
PQconnectStart("<replaceable>connection_info_string</replaceable>")</literal>.
! If <varname>conn</varname> is null, then <application>libpq</application> has been unable to allocate a new
<structname>PGconn</structname>
! structure. Otherwise, a valid <structname>PGconn</structname> pointer is returned (though not yet
! representing a valid connection to the database). On return from
! <function>PQconnectStart</function>, call <literal>status = PQstatus(conn)</literal>. If
<varname>status</varname>equals
! <symbol>CONNECTION_BAD</symbol>, <function>PQconnectStart</function> has failed.
</para>
<para>
! If <function>PQconnectStart</function> succeeds, the next stage is to poll
! <application>libpq</application> so that it can proceed with the connection sequence.
Use <function>PQsocket(conn)</function> to obtain the descriptor of the
socket underlying the database connection.
Loop thus: If <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_READING</symbol>, wait until the socket is ready to
read (as indicated by <function>select()</function>, <function>poll()</function>, or
--- 326,352 ----
</para>
<para>
! To begin a nonblocking connection request,
! call <function>PQconnectStart</function>
! or <function>PQconnectStartParams</function>. If the result is null,
! then <application>libpq</application> has been unable to allocate a
! new <structname>PGconn</structname> structure. Otherwise, a
! valid <structname>PGconn</structname> pointer is returned (though not
! yet representing a valid connection to the database). Next
! call <literal>PQstatus(conn)</literal>. If the result
! is <symbol>CONNECTION_BAD</symbol>, the connection attempt has already
! failed, typically because of invalid connection parameters.
</para>
<para>
! If <function>PQconnectStart</function>
! or <function>PQconnectStartParams</function> succeeds, the next stage
! is to poll <application>libpq</application> so that it can proceed with
! the connection sequence.
Use <function>PQsocket(conn)</function> to obtain the descriptor of the
socket underlying the database connection.
+ (Caution: do not assume that the socket remains the same
+ across <function>PQconnectPoll</function> calls.)
Loop thus: If <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_READING</symbol>, wait until the socket is ready to
read (as indicated by <function>select()</function>, <function>poll()</function>, or
*************** PostgresPollingStatusType PQconnectPoll(
*** 352,360 ****
Conversely, if <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_WRITING</symbol>, wait until the socket is ready
to write, then call <function>PQconnectPoll(conn)</function> again.
! If you have yet to call
! <function>PQconnectPoll</function>, i.e., just after the call to
! <function>PQconnectStart</function>, behave as if it last returned
<symbol>PGRES_POLLING_WRITING</symbol>. Continue this loop until
<function>PQconnectPoll(conn)</function> returns
<symbol>PGRES_POLLING_FAILED</symbol>, indicating the connection procedure
--- 355,362 ----
Conversely, if <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_WRITING</symbol>, wait until the socket is ready
to write, then call <function>PQconnectPoll(conn)</function> again.
! On the first iteration, i.e. if you have yet to call
! <function>PQconnectPoll</function>, behave as if it last returned
<symbol>PGRES_POLLING_WRITING</symbol>. Continue this loop until
<function>PQconnectPoll(conn)</function> returns
<symbol>PGRES_POLLING_FAILED</symbol>, indicating the connection procedure
*************** switch(PQstatus(conn))
*** 479,488 ****
</para>
<para>
! Note that if <function>PQconnectStart</function> returns a non-null pointer, you must call
! <function>PQfinish</function> when you are finished with it, in order to dispose of
! the structure and any associated memory blocks. This must be done even if
! the connection attempt fails or is abandoned.
</para>
</listitem>
</varlistentry>
--- 481,492 ----
</para>
<para>
! Note that when <function>PQconnectStart</function>
! or <function>PQconnectStartParams</function> returns a non-null
! pointer, you must call <function>PQfinish</function> when you are
! finished with it, in order to dispose of the structure and any
! associated memory blocks. This must be done even if the connection
! attempt fails or is abandoned.
</para>
</listitem>
</varlistentry>
*************** postgresql://%2Fvar%2Flib%2Fpostgresql/d
*** 913,919 ****
It is possible to specify multiple hosts to connect to, so that they are
tried in the given order. In the Keyword/Value format, the <literal>host</literal>,
<literal>hostaddr</literal>, and <literal>port</literal> options accept a comma-separated
! list of values. The same number of elements must be given in each option, such
that e.g. the first <literal>hostaddr</literal> corresponds to the first host name,
the second <literal>hostaddr</literal> corresponds to the second host name, and so
forth. As an exception, if only one <literal>port</literal> is specified, it
--- 917,924 ----
It is possible to specify multiple hosts to connect to, so that they are
tried in the given order. In the Keyword/Value format, the <literal>host</literal>,
<literal>hostaddr</literal>, and <literal>port</literal> options accept a comma-separated
! list of values. The same number of elements must be given in each
! option that is specified, such
that e.g. the first <literal>hostaddr</literal> corresponds to the first host name,
the second <literal>hostaddr</literal> corresponds to the second host name, and so
forth. As an exception, if only one <literal>port</literal> is specified, it
*************** postgresql://%2Fvar%2Flib%2Fpostgresql/d
*** 922,930 ****
<para>
In the connection URI format, you can list multiple <literal>host:port</literal> pairs
! separated by commas, in the <literal>host</literal> component of the URI. In either
! format, a single host name can also translate to multiple network addresses. A
! common example of this is a host that has both an IPv4 and an IPv6 address.
</para>
<para>
--- 927,939 ----
<para>
In the connection URI format, you can list multiple <literal>host:port</literal> pairs
! separated by commas, in the <literal>host</literal> component of the URI.
! </para>
!
! <para>
! In either format, a single host name can translate to multiple network
! addresses. A common example of this is a host that has both an IPv4 and
! an IPv6 address.
</para>
<para>
*************** postgresql://%2Fvar%2Flib%2Fpostgresql/d
*** 958,966 ****
Name of host to connect to.<indexterm><primary>host name</primary></indexterm>
If a host name begins with a slash, it specifies Unix-domain
communication rather than TCP/IP communication; the value is the
! name of the directory in which the socket file is stored. If
! multiple host names are specified, each will be tried in turn in
! the order given. The default behavior when <literal>host</literal> is
not specified, or is empty, is to connect to a Unix-domain
socket<indexterm><primary>Unix domain socket</primary></indexterm> in
<filename>/tmp</filename> (or whatever socket directory was specified
--- 967,974 ----
Name of host to connect to.<indexterm><primary>host name</primary></indexterm>
If a host name begins with a slash, it specifies Unix-domain
communication rather than TCP/IP communication; the value is the
! name of the directory in which the socket file is stored.
! The default behavior when <literal>host</literal> is
not specified, or is empty, is to connect to a Unix-domain
socket<indexterm><primary>Unix domain socket</primary></indexterm> in
<filename>/tmp</filename> (or whatever socket directory was specified
*************** postgresql://%2Fvar%2Flib%2Fpostgresql/d
*** 997,1004 ****
<itemizedlist>
<listitem>
<para>
! If <literal>host</literal> is specified without <literal>hostaddr</literal>,
! a host name lookup occurs.
</para>
</listitem>
<listitem>
--- 1005,1016 ----
<itemizedlist>
<listitem>
<para>
! If <literal>host</literal> is specified
! without <literal>hostaddr</literal>, a host name lookup occurs.
! (When using <function>PQconnectPoll</function>, the lookup occurs
! when <function>PQconnectPoll</function> first considers this host
! name, and it may cause <function>PQconnectPoll</function> to block
! for a significant amount of time.)
</para>
</listitem>
<listitem>
В списке pgsql-hackers по дате отправления: