Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rTYXv-0048VN-Aw for pgsql-hackers@arkaria.postgresql.org; Sat, 27 Jan 2024 02:35:52 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rTYXs-003meZ-F1 for pgsql-hackers@arkaria.postgresql.org; Sat, 27 Jan 2024 02:35:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rTYXr-003meQ-Um for pgsql-hackers@lists.postgresql.org; Sat, 27 Jan 2024 02:35:48 +0000 Received: from mail-yb1-xb2f.google.com ([2607:f8b0:4864:20::b2f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rTYXo-003vBh-I6 for pgsql-hackers@postgresql.org; Sat, 27 Jan 2024 02:35:46 +0000 Received: by mail-yb1-xb2f.google.com with SMTP id 3f1490d57ef6-db4364ecd6aso816442276.2 for ; Fri, 26 Jan 2024 18:35:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1706322942; x=1706927742; darn=postgresql.org; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Tf8YowupwVhEYSC/9g7yfg8NbWq8KX2QuBz3e4SFJ1o=; b=IRllx6GHQNjl4lLZi0L2fCNM7DMeUHHxRKvIaEw26e8rXIl6P7HKyHtPeg6R0b/U20 aunALZbO8tyLupTP5++3LiTU/dsnUP2GBkurEePSUDHp/qeoYFA22p8yP1cpSB/iN+P2 9M1un+GozncfvZAGIFky4ly8NQIGNE+RBH7XE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706322942; x=1706927742; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Tf8YowupwVhEYSC/9g7yfg8NbWq8KX2QuBz3e4SFJ1o=; b=i3h8Yn5Cy2z3mScGV19kq7WNQ/2SvaV3d/ECRM6REAEGuXdvbfJx2XdkQU9OrAMWTQ +Rwq9lI7CT0srOz2abth1NZh12Omz1Q6IuOzWzVIzPwoaoERHOCuXhpj4Lxw/nERk2R/ yG0bUGQ9rAvKekFZ18Rs4XuVf8mQwKcrwNxVtdFYTcc1KewILx+eEfIBZQdDeP9Tqi65 PP2LiXkRMtX1Inzfv+GJAPeM/OovLfLG7J7BUOUFs9Zk94aREtoWkMny2ymx9RSpdSNS cWZgqEFOZRvLPMFnUH5RRCP1OzrBhoLKr6HuAGzgAxbJGaZSTr6DYzVyJFtP++OVH2Hx m90A== X-Gm-Message-State: AOJu0YwX0PXGyHOnj7uMisrk+fyDDitPQOqXOAWBI0hrdO72/E5/glpU wKUhRE1AjkCi9bB0Eb9+O9rKVgYeVZzNN4nMsLDLnJRRAgmkI4G7aL4933ZmMw== X-Google-Smtp-Source: AGHT+IHWwQhrufApnnh+NVspEGThkvIRRBneIOtyO4vb17l3JGGoR7nEMCFjifo78Rrfz9NmO8JasA== X-Received: by 2002:a81:af64:0:b0:600:3d0d:a81e with SMTP id x36-20020a81af64000000b006003d0da81emr585232ywj.34.1706322942260; Fri, 26 Jan 2024 18:35:42 -0800 (PST) Received: from google.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id w69-20020a0dd448000000b005f66a83db14sm797230ywd.131.2024.01.26.18.35.41 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 26 Jan 2024 18:35:41 -0800 (PST) Date: Fri, 26 Jan 2024 18:35:39 -0800 From: Noah Misch To: Fujii Masao Cc: pgsql-hackers@postgresql.org Subject: Re: dblink query interruptibility Message-ID: <20240127023539.5f.nmisch@google.com> References: <20231122012945.74@rfd.leadboat.com> <20240124204532.1b.nmisch@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, Jan 25, 2024 at 12:28:43PM +0900, Fujii Masao wrote: > On Thu, Jan 25, 2024 at 5:45 AM Noah Misch wrote: > > On Thu, Jan 25, 2024 at 04:23:39AM +0900, Fujii Masao wrote: > > > I found that this patch was committed at d3c5f37dd5 and changed the > > > error message in postgres_fdw slightly. Here's an example: > > > > > > #1. Begin a new transaction. > > > #2. Execute a query accessing to a foreign table, like SELECT * FROM > > > > > > #3. Terminate the *remote* session corresponding to the foreign table. > > > #4. Commit the transaction, and then currently the following error > > > message is output. > > > > > > ERROR: FATAL: terminating connection due to administrator command > > > server closed the connection unexpectedly > > > This probably means the server terminated abnormally > > > before or while processing the request. > > > invalid socket > > > > > > Previously, before commit d3c5f37dd5, the error message at #4 did not > > > include "invalid socket." Now, after the commit, it does. Other clients have witnessed the extra "invalid socket" message: https://dba.stackexchange.com/questions/335081/how-to-investigate-intermittent-postgres-connection-errors https://stackoverflow.com/questions/77781358/pgbackrest-backup-error-with-exit-code-57 https://github.com/timescale/timescaledb/issues/102 > > > + /* Consume whatever data is available from the socket */ > > > + if (PQconsumeInput(conn) == 0) > > > + { > > > + /* trouble; expect PQgetResult() to return NULL */ > > > + break; > > > + } > > > + } > > > + > > > + /* Now we can collect and return the next PGresult */ > > > + return PQgetResult(conn); > > > > > > This code appears to cause the change. When the remote session ends, > > > PQconsumeInput() returns 0 and marks conn->socket as invalid. > > > Subsequent PQgetResult() calls pqWait(), detecting the invalid socket > > > and appending "invalid socket" to the error message. What do you think of making PQconsumeInput() set PGASYNC_READY and CONNECTION_BAD in this case? Since libpq appended "server closed the connection unexpectedly", it knows those indicators are correct. That way, PQgetResult() won't issue a pointless pqWait() call. > > > I think the "invalid socket" message is unsuitable in this scenario, > > > and PQgetResult() should not be called after PQconsumeInput() returns > > > 0. Thought? > > > > The documentation is absolute about the necessity of PQgetResult(): > > The documentation looks unclear to me regarding what should be done > when PQconsumeInput() returns 0. So I'm not sure if PQgetResult() > must be called even in that case. I agree PQconsumeInput() docs don't specify how to interpret it returning 0. > As far as I read some functions like libpqrcv_PQgetResult() that use > PQconsumeInput(), it appears that they basically report the error message > using PQerrorMessage(), without calling PQgetResult(), > when PQconsumeInput() returns 0. libpqrcv_PQgetResult() is part of walreceiver, where any ERROR becomes FATAL. Hence, it can't hurt anything by eagerly skipping to ERROR. I designed libpqsrv_exec() to mimic PQexec() as closely as possible, so it would be a drop-in replacement for arbitrary callers. Ideally, accepting interrupts would be the only caller-visible difference. I know of three ways PQconsumeInput() can return 0, along with my untested estimates of how they work: a. Protocol violation. handleSyncLoss() sets PGASYNC_READY and CONNECTION_BAD. PQgetResult() is optional. b. Connection broken. PQgetResult() is optional. c. ENOMEM. PGASYNC_ and CONNECTION_ status don't change. Applications choose among (c1) free memory and retry, (c2) close the connection, or (c3) call PQgetResult() to break protocol sync and set PGASYNC_IDLE: Comparing PQconsumeInput() with the PQgetResult() block under "while (conn->asyncStatus == PGASYNC_BUSY)", there's a key difference that PQgetResult() sets PGASYNC_IDLE on most errors, including ENOMEM. That prevents PQexec() subroutine PQexecFinish() from busy looping on ENOMEM, but I suspect that also silently breaks protocol sync. While we could change it from (c3) to (c2) by dropping the connection via handleSyncLoss() or equivalent, I'm not confident about that being better. libpqsrv_exec() implements (c3) by way of calling PQgetResult() after PQconsumeInput() fails. If PQisBusy(), the same ENOMEM typically will repeat, yielding (c3). If memory became available in that brief time, PQgetResult() may instead block. That blocking is unwanted but unimportant.