Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5d43c3c

Browse files
committed
Fix query cancellation handling in psql
The refactoring done in a4fd3aa for query cancellation has messed up with the logic in psql by mixing CancelRequested and cancel_pressed, breaking for example \watch. The former would be switched to true if a cancellation request has been attempted and that it actually succeeded, and the latter tracks if a cancellation attempt has been done. This commit brings back the code of psql to a state consistent to what it was before a4fd3aa, without giving up on the refactoring pieces introduced. It should be actually possible to merge more both flags as their concepts are close enough, however note that psql's --single-step mode relies on cancel_pressed to be always set, so this requires more careful analysis left for later. While on it, fix the declarations of CancelRequested (in cancel.c) and cancel_pressed (in psql) to be volatile sig_atomic_t. Previously, both were declared as booleans, which should be fine on modern platforms, but the C standard recommends the use of sig_atomic_t for variables used in signal handlers. Note that since its introduction in a179232, CancelRequested declaration was not volatile. Reported-by: Jeff Janes Author: Michael Paquier Discussion: https://postgr.es/m/CAMkU=1zpoUDGKqWKuMWkj7t-bOCaJDx0r=5te_-d0B2HVLABXg@mail.gmail.com
1 parent b925a00 commit 5d43c3c

File tree

5 files changed

+29
-25
lines changed

5 files changed

+29
-25
lines changed

src/bin/psql/common.c

+9-19
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ NoticeProcessor(void *arg, const char *message)
233233
*
234234
* SIGINT is supposed to abort all long-running psql operations, not only
235235
* database queries. In most places, this is accomplished by checking
236-
* CancelRequested during long-running loops. However, that won't work when
236+
* cancel_pressed during long-running loops. However, that won't work when
237237
* blocked on user input (in readline() or fgets()). In those places, we
238238
* set sigint_interrupt_enabled true while blocked, instructing the signal
239239
* catcher to longjmp through sigint_interrupt_jmp. We assume readline and
@@ -246,32 +246,22 @@ volatile bool sigint_interrupt_enabled = false;
246246

247247
sigjmp_buf sigint_interrupt_jmp;
248248

249-
#ifndef WIN32
250-
251249
static void
252250
psql_cancel_callback(void)
253251
{
252+
#ifndef WIN32
254253
/* if we are waiting for input, longjmp out of it */
255254
if (sigint_interrupt_enabled)
256255
{
257256
sigint_interrupt_enabled = false;
258257
siglongjmp(sigint_interrupt_jmp, 1);
259258
}
259+
#endif
260260

261261
/* else, set cancel flag to stop any long-running loops */
262-
CancelRequested = true;
263-
}
264-
265-
#else
266-
267-
static void
268-
psql_cancel_callback(void)
269-
{
270-
/* nothing to do here */
262+
cancel_pressed = true;
271263
}
272264

273-
#endif /* !WIN32 */
274-
275265
void
276266
psql_setup_cancel_handler(void)
277267
{
@@ -638,7 +628,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt)
638628
* consumed. The user's intention, though, is to cancel the entire watch
639629
* process, so detect a sent cancellation request and exit in this case.
640630
*/
641-
if (CancelRequested)
631+
if (cancel_pressed)
642632
{
643633
PQclear(res);
644634
return 0;
@@ -838,8 +828,8 @@ ExecQueryTuples(const PGresult *result)
838828
{
839829
const char *query = PQgetvalue(result, r, c);
840830

841-
/* Abandon execution if CancelRequested */
842-
if (CancelRequested)
831+
/* Abandon execution if cancel_pressed */
832+
if (cancel_pressed)
843833
goto loop_exit;
844834

845835
/*
@@ -1207,7 +1197,7 @@ SendQuery(const char *query)
12071197
if (fgets(buf, sizeof(buf), stdin) != NULL)
12081198
if (buf[0] == 'x')
12091199
goto sendquery_cleanup;
1210-
if (CancelRequested)
1200+
if (cancel_pressed)
12111201
goto sendquery_cleanup;
12121202
}
12131203
else if (pset.echo == PSQL_ECHO_QUERIES)
@@ -1751,7 +1741,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
17511741
* writing things to the stream, we presume $PAGER has disappeared and
17521742
* stop bothering to pull down more data.
17531743
*/
1754-
if (ntuples < fetch_count || CancelRequested || flush_error ||
1744+
if (ntuples < fetch_count || cancel_pressed || flush_error ||
17551745
ferror(fout))
17561746
break;
17571747
}

src/fe_utils/cancel.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#include "postgres_fe.h"
1818

19-
#include <signal.h>
2019
#include <unistd.h>
2120

2221
#include "fe_utils/cancel.h"
@@ -37,8 +36,20 @@
3736
(void) rc_; \
3837
} while (0)
3938

39+
/*
40+
* Contains all the information needed to cancel a query issued from
41+
* a database connection to the backend.
42+
*/
4043
static PGcancel *volatile cancelConn = NULL;
41-
bool CancelRequested = false;
44+
45+
/*
46+
* CancelRequested tracks if a cancellation request has completed after
47+
* a signal interruption. Note that if cancelConn is not set, in short
48+
* if SetCancelConn() was never called or if ResetCancelConn() freed
49+
* the cancellation object, then CancelRequested is switched to true after
50+
* all cancellation attempts.
51+
*/
52+
volatile sig_atomic_t CancelRequested = false;
4253

4354
#ifdef WIN32
4455
static CRITICAL_SECTION cancelConnLock;

src/fe_utils/print.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
#include <limits.h>
2121
#include <math.h>
22-
#include <signal.h>
2322
#include <unistd.h>
2423

2524
#ifndef WIN32
@@ -41,7 +40,7 @@
4140
* Note: print.c's general strategy for when to check cancel_pressed is to do
4241
* so at completion of each row of output.
4342
*/
44-
volatile bool cancel_pressed = false;
43+
volatile sig_atomic_t cancel_pressed = false;
4544

4645
static bool always_ignore_sigpipe = false;
4746

src/include/fe_utils/cancel.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
#ifndef CANCEL_H
1515
#define CANCEL_H
1616

17+
#include <signal.h>
18+
1719
#include "libpq-fe.h"
1820

19-
extern bool CancelRequested;
21+
extern volatile sig_atomic_t CancelRequested;
2022

2123
extern void SetCancelConn(PGconn *conn);
2224
extern void ResetCancelConn(void);

src/include/fe_utils/print.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef PRINT_H
1414
#define PRINT_H
1515

16+
#include <signal.h>
17+
1618
#include "libpq-fe.h"
1719

1820

@@ -175,7 +177,7 @@ typedef struct printQueryOpt
175177
} printQueryOpt;
176178

177179

178-
extern volatile bool cancel_pressed;
180+
extern volatile sig_atomic_t cancel_pressed;
179181

180182
extern const printTextFormat pg_asciiformat;
181183
extern const printTextFormat pg_asciiformat_old;

0 commit comments

Comments
 (0)