From c7eee6f7c3f5426964c07c6bd9a44247c2017d4e Mon Sep 17 00:00:00 2001 From: Jelte Fennema Date: Thu, 6 Jan 2022 15:11:22 +0100 Subject: [PATCH 1/3] Refactor to remove internal_cancel helper To simplify future changes to PQcancel this removes the internal_cancel helper function. Now PQrequestCancel calls PQcancel internally, instead of having both PQcancel and PQrequestCancel call the shared internal_cancel helper function. --- src/interfaces/libpq/fe-connect.c | 58 ++++++++++++------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 9b6a6939f0..85fce856a5 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -4406,14 +4406,17 @@ PQfreeCancel(PGcancel *cancel) /* - * PQcancel and PQrequestCancel: attempt to request cancellation of the - * current operation. + * PQcancel: request query cancel * * The return value is true if the cancel request was successfully * dispatched, false if not (in which case an error message is available). * Note: successful dispatch is no guarantee that there will be any effect at * the backend. The application must read the operation result as usual. * + * On failure, an error message is stored in *errbuf, which must be of size + * errbufsize (recommended size is 256 bytes). *errbuf is not changed on + * success return. + * * CAUTION: we want this routine to be safely callable from a signal handler * (for example, an application might want to call it in a SIGINT handler). * This means we cannot use any C library routine that might be non-reentrant. @@ -4421,13 +4424,9 @@ PQfreeCancel(PGcancel *cancel) * just as dangerous. We avoid sprintf here for that reason. Building up * error messages with strcpy/strcat is tedious but should be quite safe. * We also save/restore errno in case the signal handler support doesn't. - * - * internal_cancel() is an internal helper function to make code-sharing - * between the two versions of the cancel function possible. */ -static int -internal_cancel(SockAddr *raddr, int be_pid, int be_key, - char *errbuf, int errbufsize) +int +PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) { int save_errno = SOCK_ERRNO; pgsocket tmpsock = PGINVALID_SOCKET; @@ -4439,18 +4438,24 @@ internal_cancel(SockAddr *raddr, int be_pid, int be_key, CancelRequestPacket cp; } crp; + if (!cancel) + { + strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize); + return false; + } + /* * We need to open a temporary connection to the postmaster. Do this with * only kernel calls. */ - if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET) + if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET) { strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize); goto cancel_errReturn; } retry3: - if (connect(tmpsock, (struct sockaddr *) &raddr->addr, - raddr->salen) < 0) + if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr, + cancel->raddr.salen) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ @@ -4467,8 +4472,8 @@ retry3: crp.packetlen = pg_hton32((uint32) sizeof(crp)); crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); - crp.cp.backendPID = pg_hton32(be_pid); - crp.cp.cancelAuthCode = pg_hton32(be_key); + crp.cp.backendPID = pg_hton32(cancel->be_pid); + crp.cp.cancelAuthCode = pg_hton32(cancel->be_key); retry4: if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) @@ -4520,27 +4525,6 @@ cancel_errReturn: return false; } -/* - * PQcancel: request query cancel - * - * Returns true if able to send the cancel request, false if not. - * - * On failure, an error message is stored in *errbuf, which must be of size - * errbufsize (recommended size is 256 bytes). *errbuf is not changed on - * success return. - */ -int -PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) -{ - if (!cancel) - { - strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize); - return false; - } - - return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key, - errbuf, errbufsize); -} /* * PQrequestCancel: old, not thread-safe function for requesting query cancel @@ -4558,6 +4542,7 @@ int PQrequestCancel(PGconn *conn) { int r; + PGcancel *cancel; /* Check we have an open connection */ if (!conn) @@ -4573,8 +4558,9 @@ PQrequestCancel(PGconn *conn) return false; } - r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key, - conn->errorMessage.data, conn->errorMessage.maxlen); + cancel = PQgetCancel(conn); + r = PQcancel(cancel, conn->errorMessage.data, conn->errorMessage.maxlen); + PQfreeCancel(cancel); if (!r) conn->errorMessage.len = strlen(conn->errorMessage.data); -- 2.17.1