From 68f723ff97352cf458e6cfb417cd503f70990a96 Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Thu, 8 Oct 2026 20:10:21 +0000 Subject: [PATCH v1 2/2] Reapply "graceful shutdown" changes for Windows. This reverts commit 29992a6a509b256efc4ac560a1586b51a64b2637. a8458f508a7 closed the race that lost FD_CLOSE events, which was the reason for the revert, so try again. --- src/backend/libpq/pqcomm.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 3704d121003..c0445f64546 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -377,15 +377,30 @@ socket_close(int code, Datum arg) secure_close(MyProcPort); /* - * Formerly we did an explicit close() here, but it seems better to - * leave the socket open until the process dies. This allows clients - * to perform a "synchronous close" if they care --- wait till the - * transport layer reports connection closure, and you can be sure the - * backend has exited. + * On most platforms, we leave the socket open until the process dies. + * This allows clients to perform a "synchronous close" if they care + * --- wait till the transport layer reports connection closure, and + * you can be sure the backend has exited. Saves a kernel call, too. * - * We do set sock to PGINVALID_SOCKET to prevent any further I/O, - * though. + * However, that does not work on Windows: if the kernel closes the + * socket it will invoke an "abortive shutdown" that discards any data + * not yet sent to the client. (This is a flat-out violation of the + * TCP RFCs, but count on Microsoft not to care about that.) To get + * the spec-compliant "graceful shutdown" behavior, we must invoke + * closesocket() explicitly. When using OpenSSL, it seems that clean + * shutdown also requires an explicit shutdown() call. + * + * This code runs late enough during process shutdown that we should + * have finished all externally-visible shutdown activities, so that + * in principle it's good enough to act as a synchronous close on + * Windows too. But it's a lot more fragile than the other way. */ +#ifdef WIN32 + shutdown(MyProcPort->sock, SD_SEND); + closesocket(MyProcPort->sock); +#endif + + /* In any case, set sock to PGINVALID_SOCKET to prevent further I/O */ MyProcPort->sock = PGINVALID_SOCKET; } } -- 2.55.0