Re: psql client does not handle WSAEWOULDBLOCK on Windows

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: psql client does not handle WSAEWOULDBLOCK on Windows
Дата
Msg-id 1768846.1759691684@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: psql client does not handle WSAEWOULDBLOCK on Windows  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-hackers
I wrote:
> Michael Paquier <michael@paquier.xyz> writes:
>> Also, what about pqsecure_raw_write() in pqsecure_open_gss()?
>> Shouldn't the same check apply?

> Yeah, I think we pretty much need to use SOCK_ERRNO, SOCK_ERRNO_SET,
> and SOCK_STRERROR (if relevant) throughout fe-secure-gssapi.c.

Since nothing seems to be happening here, I took another look and
decided that the required changes are really pretty straightforward.
fe-secure-gssapi.c doesn't contain any strerror calls, and its
touches of errno all appear to relate to socket errors, so we can
just change them all.  As attached.

> Like you, I'm not really in a position to test this on Windows ...

I'm still not, but it's straightforward enough that I'm willing to
push on my own authority.  I'll just put this up for long enough
to make sure that the cfbot is happy with it --- though I think
it's not building with GSSAPI on Windows, so that may prove little.

            regards, tom lane

From 36f3ee942ef12801e52ce3fc82204455345939a6 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 5 Oct 2025 15:05:38 -0400
Subject: [PATCH v2] Use SOCK_ERRNO[_SET] in fe-secure-gssapi.c.

On Windows, this code did not handle error conditions correctly at
all, since it looked at "errno" which is not used for socket-related
errors on that platform.  This resulted, for example, in failure
to connect to a PostgreSQL server with GSSAPI enabled.

We have a convention for dealing with this within libpq, which is to
use SOCK_ERRNO and SOCK_ERRNO_SET rather than touching errno directly;
but the GSSAPI code is a relative latecomer and did not get that memo.
(The equivalent backend code continues to use errno, because the
backend does this differently.  Maybe libpq's approach should be
rethought someday.)

Author: Ning Wu <ning94803@gmail.com>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAFGqpvg-pRw=cdsUpKYfwY6D3d-m9tw8WMcAEE7HHWfm-oYWvw@mail.gmail.com
Backpatch-through: 13
---
 src/interfaces/libpq/fe-secure-gssapi.c | 27 ++++++++++++++-----------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c
index bc9e1ce06fa..843b31e175f 100644
--- a/src/interfaces/libpq/fe-secure-gssapi.c
+++ b/src/interfaces/libpq/fe-secure-gssapi.c
@@ -121,7 +121,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
     {
         appendPQExpBufferStr(&conn->errorMessage,
                              "GSSAPI caller failed to retransmit all data needing to be retried\n");
-        errno = EINVAL;
+        SOCK_ERRNO_SET(EINVAL);
         return -1;
     }

@@ -199,14 +199,14 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
         if (major != GSS_S_COMPLETE)
         {
             pg_GSS_error(libpq_gettext("GSSAPI wrap error"), conn, major, minor);
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             goto cleanup;
         }

         if (conf_state == 0)
         {
             libpq_append_conn_error(conn, "outgoing GSSAPI message would not use confidentiality");
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             goto cleanup;
         }

@@ -215,7 +215,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
             libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)",
                                     (size_t) output.length,
                                     PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             goto cleanup;
         }

@@ -341,7 +341,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
             /* If we still haven't got the length, return to the caller */
             if (PqGSSRecvLength < sizeof(uint32))
             {
-                errno = EWOULDBLOCK;
+                SOCK_ERRNO_SET(EWOULDBLOCK);
                 return -1;
             }
         }
@@ -354,7 +354,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
             libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)",
                                     (size_t) input.length,
                                     PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             return -1;
         }

@@ -373,7 +373,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
         /* If we don't yet have the whole packet, return to the caller */
         if (PqGSSRecvLength - sizeof(uint32) < input.length)
         {
-            errno = EWOULDBLOCK;
+            SOCK_ERRNO_SET(EWOULDBLOCK);
             return -1;
         }

@@ -393,7 +393,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
             pg_GSS_error(libpq_gettext("GSSAPI unwrap error"), conn,
                          major, minor);
             ret = -1;
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             goto cleanup;
         }

@@ -401,7 +401,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
         {
             libpq_append_conn_error(conn, "incoming GSSAPI message did not use confidentiality");
             ret = -1;
-            errno = EIO;        /* for lack of a better idea */
+            SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
             goto cleanup;
         }

@@ -437,7 +437,8 @@ gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
     *ret = pqsecure_raw_read(conn, recv_buffer, length);
     if (*ret < 0)
     {
-        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+        if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+            SOCK_ERRNO == EINTR)
             return PGRES_POLLING_READING;
         else
             return PGRES_POLLING_FAILED;
@@ -457,7 +458,8 @@ gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
         *ret = pqsecure_raw_read(conn, recv_buffer, length);
         if (*ret < 0)
         {
-            if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+            if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+                SOCK_ERRNO == EINTR)
                 return PGRES_POLLING_READING;
             else
                 return PGRES_POLLING_FAILED;
@@ -520,7 +522,8 @@ pqsecure_open_gss(PGconn *conn)
         ret = pqsecure_raw_write(conn, PqGSSSendBuffer + PqGSSSendNext, amount);
         if (ret < 0)
         {
-            if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+            if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+                SOCK_ERRNO == EINTR)
                 return PGRES_POLLING_WRITING;
             else
                 return PGRES_POLLING_FAILED;
--
2.43.7


В списке pgsql-hackers по дате отправления: