Skip to content

Commit 335fa5a

Browse files
committed
Fix thinko in PQisBusy().
In commit 1f39a1c I made PQisBusy consider conn->write_failed, but that is now looking like complete brain fade. In the first place, the logic is quite wrong: it ought to be like "and not" rather than "or". This meant that once we'd gotten into a write_failed state, PQisBusy would always return true, probably causing the calling application to iterate its loop until PQconsumeInput returns a hard failure thanks to connection loss. That's not what we want: the intended behavior is to return an error PGresult, which the application probably has much cleaner support for. But in the second place, checking write_failed here seems like the wrong thing anyway. The idea of the write_failed mechanism is to postpone handling of a write failure until we've read all we can from the server; so that flag should not interfere with input-processing behavior. (Compare 7247e24.) What we *should* check for is status = CONNECTION_BAD, ie, socket already closed. (Most places that close the socket don't touch asyncStatus, but they do reset status.) This primarily ensures that if PQisBusy() returns true then there is an open socket, which is assumed by several call sites in our own code, and probably other applications too. While at it, fix a nearby thinko in libpq's my_sock_write: we should only consult errno for res < 0, not res == 0. This is harmless since pqsecure_raw_write would force errno to zero in such a case, but it still could confuse readers. Noted by Andres Freund. Backpatch to v12 where 1f39a1c came in. Discussion: https://postgr.es/m/20220211011025.ek7exh6owpzjyudn@alap3.anarazel.de
1 parent 52377bb commit 335fa5a

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

src/interfaces/libpq/fe-exec.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,10 +1957,14 @@ PQisBusy(PGconn *conn)
19571957
parseInput(conn);
19581958

19591959
/*
1960-
* PQgetResult will return immediately in all states except BUSY, or if we
1961-
* had a write failure.
1960+
* PQgetResult will return immediately in all states except BUSY. Also,
1961+
* if we've detected read EOF and dropped the connection, we can expect
1962+
* that PQgetResult will fail immediately. Note that we do *not* check
1963+
* conn->write_failed here --- once that's become set, we know we have
1964+
* trouble, but we need to keep trying to read until we have a complete
1965+
* server message or detect read EOF.
19621966
*/
1963-
return conn->asyncStatus == PGASYNC_BUSY || conn->write_failed;
1967+
return conn->asyncStatus == PGASYNC_BUSY && conn->status != CONNECTION_BAD;
19641968
}
19651969

19661970
/*

src/interfaces/libpq/fe-secure-openssl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,7 @@ my_sock_write(BIO *h, const char *buf, int size)
16821682

16831683
res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
16841684
BIO_clear_retry_flags(h);
1685-
if (res <= 0)
1685+
if (res < 0)
16861686
{
16871687
/* If we were interrupted, tell caller to retry */
16881688
switch (SOCK_ERRNO)

0 commit comments

Comments
 (0)