PostgreSQL Source Code git master
Loading...
Searching...
No Matches
cancel.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------
2 *
3 * Query cancellation support for frontend code
4 *
5 * Assorted utility functions to control query cancellation with signal
6 * handler for SIGINT.
7 *
8 *
9 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
11 *
12 * src/fe_utils/cancel.c
13 *
14 *------------------------------------------------------------------------
15 */
16
17#include "postgres_fe.h"
18
19#include <unistd.h>
20
21#include "common/connect.h"
22#include "fe_utils/cancel.h"
24
25
26/*
27 * Write a simple string to stderr --- must be safe in a signal handler.
28 * We ignore the write() result since there's not much we could do about it.
29 * Certain compilers make that harder than it ought to be.
30 */
31#define write_stderr(str) \
32 do { \
33 const char *str_ = (str); \
34 int rc_; \
35 rc_ = write(fileno(stderr), str_, strlen(str_)); \
36 (void) rc_; \
37 } while (0)
38
39/*
40 * Contains all the information needed to cancel a query issued from
41 * a database connection to the backend.
42 */
43static PGcancel *volatile cancelConn = NULL;
44
45/*
46 * Predetermined localized error strings --- needed to avoid trying
47 * to call gettext() from a signal handler.
48 */
49static const char *cancel_sent_msg = NULL;
50static const char *cancel_not_sent_msg = NULL;
51
52/*
53 * CancelRequested is set when we receive SIGINT (or local equivalent).
54 * There is no provision in this module for resetting it; but applications
55 * might choose to clear it after successfully recovering from a cancel.
56 * Note that there is no guarantee that we successfully sent a Cancel request,
57 * or that the request will have any effect if we did send it.
58 */
60
61#ifdef WIN32
63#endif
64
65/*
66 * Additional callback for cancellations.
67 */
69
70
71/*
72 * SetCancelConn
73 *
74 * Set cancelConn to point to the current database connection.
75 */
76void
78{
80
81#ifdef WIN32
83#endif
84
85 /* Free the old one if we have one */
87
88 /* be sure handle_sigint doesn't use pointer while freeing */
90
91 if (oldCancelConn != NULL)
93
95
96#ifdef WIN32
98#endif
99}
100
101/*
102 * ResetCancelConn
103 *
104 * Free the current cancel connection, if any, and set to NULL.
105 */
106void
108{
110
111#ifdef WIN32
113#endif
114
116
117 /* be sure handle_sigint doesn't use pointer while freeing */
119
120 if (oldCancelConn != NULL)
122
123#ifdef WIN32
125#endif
126}
127
128
129/*
130 * Code to support query cancellation
131 *
132 * Note that sending the cancel directly from the signal handler is safe
133 * because PQcancel() is written to make it so. We use write() to report
134 * to stderr because it's better to use simple facilities in a signal
135 * handler.
136 *
137 * On Windows, the signal canceling happens on a separate thread, because
138 * that's how SetConsoleCtrlHandler works. The PQcancel function is safe
139 * for this (unlike PQrequestCancel). However, a CRITICAL_SECTION is required
140 * to protect the PGcancel structure against being changed while the signal
141 * thread is using it.
142 */
143
144#ifndef WIN32
145
146/*
147 * handle_sigint
148 *
149 * Handle interrupt signals by canceling the current command, if cancelConn
150 * is set.
151 */
152static void
154{
155 char errbuf[256];
156
157 CancelRequested = true;
158
159 if (cancel_callback != NULL)
161
162 /* Send QueryCancel if we are processing a database query */
163 if (cancelConn != NULL)
164 {
165 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
166 {
168 }
169 else
170 {
172 write_stderr(errbuf);
173 }
174 }
175}
176
177/*
178 * setup_cancel_handler
179 *
180 * Register query cancellation callback for SIGINT.
181 */
182void
184{
186 cancel_sent_msg = _("Cancel request sent\n");
187 cancel_not_sent_msg = _("Could not send cancel request: ");
188
190}
191
192#else /* WIN32 */
193
194static BOOL WINAPI
196{
197 char errbuf[256];
198
199 if (dwCtrlType == CTRL_C_EVENT ||
201 {
202 CancelRequested = true;
203
204 if (cancel_callback != NULL)
206
207 /* Send QueryCancel if we are processing a database query */
209 if (cancelConn != NULL)
210 {
211 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
212 {
214 }
215 else
216 {
218 write_stderr(errbuf);
219 }
220 }
221
223
224 return TRUE;
225 }
226 else
227 /* Return FALSE for any signals not being handled */
228 return FALSE;
229}
230
231void
232setup_cancel_handler(void (*callback) (void))
233{
235 cancel_sent_msg = _("Cancel request sent\n");
236 cancel_not_sent_msg = _("Could not send cancel request: ");
237
239
241}
242
243#endif /* WIN32 */
#define SIGNAL_ARGS
Definition c.h:1363
volatile sig_atomic_t CancelRequested
Definition cancel.c:59
static void(* cancel_callback)(void)
Definition cancel.c:68
void ResetCancelConn(void)
Definition cancel.c:107
static const char * cancel_sent_msg
Definition cancel.c:49
void SetCancelConn(PGconn *conn)
Definition cancel.c:77
static PGcancel *volatile cancelConn
Definition cancel.c:43
#define write_stderr(str)
Definition cancel.c:31
static const char * cancel_not_sent_msg
Definition cancel.c:50
void setup_cancel_handler(void(*query_cancel_callback)(void))
Definition cancel.c:183
static void handle_sigint(SIGNAL_ARGS)
Definition cancel.c:153
#define _(x)
Definition elog.c:91
PGcancel * PQgetCancel(PGconn *conn)
Definition fe-cancel.c:368
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
Definition fe-cancel.c:548
void PQfreeCancel(PGcancel *cancel)
Definition fe-cancel.c:502
#define pqsignal
Definition port.h:547
static int fb(int x)
PGconn * conn
Definition streamutil.c:52
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)