I understand that you are unhappy about something, but where the issue is
fails me, the "wtf" 3 characters are not enough to point me in the right
direction. Feel free to elaborate a little bit more:-)

I don't see why you move the "conditional.h" line out of its correct
alphabetical position (where it is now), and then add "cancel.h" next to
it also out of its correct alphabetical position.

Because "cancel.h" requires PGconn declaration, thus must appear after "libpq-fe.h", and once I put it after that letting "conditional.h" above & alone looked a little bit silly. I put cancel after conditional because it was the new addition, which is somehow logical, although not alphabetical.

Now I can put cancel before conditional, sure.

Patch v3 attached does that.

--
Fabien.
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 03bcd22996..7aab4bdf47 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -59,9 +59,10 @@
 
 #include "common/int.h"
 #include "common/logging.h"
-#include "fe_utils/conditional.h"
 #include "getopt_long.h"
 #include "libpq-fe.h"
+#include "fe_utils/cancel.h"
+#include "fe_utils/conditional.h"
 #include "pgbench.h"
 #include "portability/instr_time.h"
 
@@ -3887,6 +3888,9 @@ initGenerateData(PGconn *con)
 			exit(1);
 		}
 
+		if (CancelRequested)
+			break;
+
 		/*
 		 * If we want to stick with the original logging, print a message each
 		 * 100k inserted rows.
@@ -4057,6 +4061,9 @@ runInitSteps(const char *initialize_steps)
 	if ((con = doConnect()) == NULL)
 		exit(1);
 
+	setup_cancel_handler(NULL);
+	SetCancelConn(con);
+
 	for (step = initialize_steps; *step != '\0'; step++)
 	{
 		instr_time	start;
@@ -4120,6 +4127,7 @@ runInitSteps(const char *initialize_steps)
 	}
 
 	fprintf(stderr, "done in %.2f s (%s).\n", run_time, stats.data);
+	ResetCancelConn();
 	PQfinish(con);
 	termPQExpBuffer(&stats);
 }
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index b981ae81ff..f1d9e0298a 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -29,6 +29,7 @@
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 #include "common/logging.h"
+#include "fe_utils/cancel.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
 
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 90f6380170..0a66b71372 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -24,6 +24,7 @@
 #include "copy.h"
 #include "crosstabview.h"
 #include "fe_utils/mbprint.h"
+#include "fe_utils/cancel.h"
 #include "fe_utils/string_utils.h"
 #include "portability/instr_time.h"
 #include "settings.h"
@@ -223,6 +224,7 @@ NoticeProcessor(void *arg, const char *message)
 }
 
 
+#ifndef WIN32
 
 /*
  * Code to support query cancellation
@@ -241,7 +243,7 @@ NoticeProcessor(void *arg, const char *message)
  *
  * SIGINT is supposed to abort all long-running psql operations, not only
  * database queries.  In most places, this is accomplished by checking
- * cancel_pressed during long-running loops.  However, that won't work when
+ * CancelRequested during long-running loops.  However, that won't work when
  * blocked on user input (in readline() or fgets()).  In those places, we
  * set sigint_interrupt_enabled true while blocked, instructing the signal
  * catcher to longjmp through sigint_interrupt_jmp.  We assume readline and
@@ -252,34 +254,9 @@ volatile bool sigint_interrupt_enabled = false;
 
 sigjmp_buf	sigint_interrupt_jmp;
 
-static PGcancel *volatile cancelConn = NULL;
-
-#ifdef WIN32
-static CRITICAL_SECTION cancelConnLock;
-#endif
-
-/*
- * Write a simple string to stderr --- must be safe in a signal handler.
- * We ignore the write() result since there's not much we could do about it.
- * Certain compilers make that harder than it ought to be.
- */
-#define write_stderr(str) \
-	do { \
-		const char *str_ = (str); \
-		int		rc_; \
-		rc_ = write(fileno(stderr), str_, strlen(str_)); \
-		(void) rc_; \
-	} while (0)
-
-
-#ifndef WIN32
-
 static void
-handle_sigint(SIGNAL_ARGS)
+psql_sigint_callback(void)
 {
-	int			save_errno = errno;
-	char		errbuf[256];
-
 	/* if we are waiting for input, longjmp out of it */
 	if (sigint_interrupt_enabled)
 	{
@@ -288,74 +265,20 @@ handle_sigint(SIGNAL_ARGS)
 	}
 
 	/* else, set cancel flag to stop any long-running loops */
-	cancel_pressed = true;
-
-	/* and send QueryCancel if we are processing a database query */
-	if (cancelConn != NULL)
-	{
-		if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
-			write_stderr("Cancel request sent\n");
-		else
-		{
-			write_stderr("Could not send cancel request: ");
-			write_stderr(errbuf);
-		}
-	}
-
-	errno = save_errno;			/* just in case the write changed it */
+	CancelRequested = true;
 }
 
-void
-setup_cancel_handler(void)
-{
-	pqsignal(SIGINT, handle_sigint);
-}
-#else							/* WIN32 */
-
-static BOOL WINAPI
-consoleHandler(DWORD dwCtrlType)
-{
-	char		errbuf[256];
-
-	if (dwCtrlType == CTRL_C_EVENT ||
-		dwCtrlType == CTRL_BREAK_EVENT)
-	{
-		/*
-		 * Can't longjmp here, because we are in wrong thread :-(
-		 */
-
-		/* set cancel flag to stop any long-running loops */
-		cancel_pressed = true;
-
-		/* and send QueryCancel if we are processing a database query */
-		EnterCriticalSection(&cancelConnLock);
-		if (cancelConn != NULL)
-		{
-			if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
-				write_stderr("Cancel request sent\n");
-			else
-			{
-				write_stderr("Could not send cancel request: ");
-				write_stderr(errbuf);
-			}
-		}
-		LeaveCriticalSection(&cancelConnLock);
-
-		return TRUE;
-	}
-	else
-		/* Return FALSE for any signals not being handled */
-		return FALSE;
-}
+#endif /* !WIN32 */
 
 void
-setup_cancel_handler(void)
+psql_setup_cancel_handler(void)
 {
-	InitializeCriticalSection(&cancelConnLock);
-
-	SetConsoleCtrlHandler(consoleHandler, TRUE);
+#ifndef WIN32
+	setup_cancel_handler(psql_sigint_callback);
+#else
+	setup_cancel_handler(NULL);
+#endif /* WIN32 */
 }
-#endif							/* WIN32 */
 
 
 /* ConnectionUp
@@ -369,7 +292,6 @@ ConnectionUp(void)
 }
 
 
-
 /* CheckConnection
  *
  * Verify that we still have a good connection to the backend, and if not,
@@ -428,62 +350,6 @@ CheckConnection(void)
 
 
 
-/*
- * SetCancelConn
- *
- * Set cancelConn to point to the current database connection.
- */
-void
-SetCancelConn(void)
-{
-	PGcancel   *oldCancelConn;
-
-#ifdef WIN32
-	EnterCriticalSection(&cancelConnLock);
-#endif
-
-	/* Free the old one if we have one */
-	oldCancelConn = cancelConn;
-	/* be sure handle_sigint doesn't use pointer while freeing */
-	cancelConn = NULL;
-
-	if (oldCancelConn != NULL)
-		PQfreeCancel(oldCancelConn);
-
-	cancelConn = PQgetCancel(pset.db);
-
-#ifdef WIN32
-	LeaveCriticalSection(&cancelConnLock);
-#endif
-}
-
-
-/*
- * ResetCancelConn
- *
- * Free the current cancel connection, if any, and set to NULL.
- */
-void
-ResetCancelConn(void)
-{
-	PGcancel   *oldCancelConn;
-
-#ifdef WIN32
-	EnterCriticalSection(&cancelConnLock);
-#endif
-
-	oldCancelConn = cancelConn;
-	/* be sure handle_sigint doesn't use pointer while freeing */
-	cancelConn = NULL;
-
-	if (oldCancelConn != NULL)
-		PQfreeCancel(oldCancelConn);
-
-#ifdef WIN32
-	LeaveCriticalSection(&cancelConnLock);
-#endif
-}
-
 
 /*
  * AcceptResult
@@ -707,7 +573,7 @@ PSQLexec(const char *query)
 			return NULL;
 	}
 
-	SetCancelConn();
+	SetCancelConn(pset.db);
 
 	res = PQexec(pset.db, query);
 
@@ -746,7 +612,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt)
 		return 0;
 	}
 
-	SetCancelConn();
+	SetCancelConn(pset.db);
 
 	if (pset.timing)
 		INSTR_TIME_SET_CURRENT(before);
@@ -773,7 +639,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt)
 	 * consumed.  The user's intention, though, is to cancel the entire watch
 	 * process, so detect a sent cancellation request and exit in this case.
 	 */
-	if (cancel_pressed)
+	if (CancelRequested)
 	{
 		PQclear(res);
 		return 0;
@@ -973,8 +839,8 @@ ExecQueryTuples(const PGresult *result)
 			{
 				const char *query = PQgetvalue(result, r, c);
 
-				/* Abandon execution if cancel_pressed */
-				if (cancel_pressed)
+				/* Abandon execution if CancelRequested */
+				if (CancelRequested)
 					goto loop_exit;
 
 				/*
@@ -1091,7 +957,7 @@ ProcessResult(PGresult **results)
 			FILE	   *copystream;
 			PGresult   *copy_result;
 
-			SetCancelConn();
+			SetCancelConn(pset.db);
 			if (result_status == PGRES_COPY_OUT)
 			{
 				bool		need_close = false;
@@ -1342,7 +1208,7 @@ SendQuery(const char *query)
 		if (fgets(buf, sizeof(buf), stdin) != NULL)
 			if (buf[0] == 'x')
 				goto sendquery_cleanup;
-		if (cancel_pressed)
+		if (CancelRequested)
 			goto sendquery_cleanup;
 	}
 	else if (pset.echo == PSQL_ECHO_QUERIES)
@@ -1360,7 +1226,7 @@ SendQuery(const char *query)
 		fflush(pset.logfile);
 	}
 
-	SetCancelConn();
+	SetCancelConn(pset.db);
 
 	transaction_status = PQtransactionStatus(pset.db);
 
@@ -1886,7 +1752,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 		 * writing things to the stream, we presume $PAGER has disappeared and
 		 * stop bothering to pull down more data.
 		 */
-		if (ntuples < fetch_count || cancel_pressed || flush_error ||
+		if (ntuples < fetch_count || CancelRequested || flush_error ||
 			ferror(fout))
 			break;
 	}
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index 282a520116..0b87ec5836 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -26,10 +26,7 @@ extern volatile bool sigint_interrupt_enabled;
 
 extern sigjmp_buf sigint_interrupt_jmp;
 
-extern void setup_cancel_handler(void);
-
-extern void SetCancelConn(void);
-extern void ResetCancelConn(void);
+extern void psql_setup_cancel_handler(void);
 
 extern PGresult *PSQLexec(const char *query);
 extern int	PSQLexecWatch(const char *query, const printQueryOpt *opt);
diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c
index 042403e0f7..b2ddb3512e 100644
--- a/src/bin/psql/large_obj.c
+++ b/src/bin/psql/large_obj.c
@@ -11,6 +11,7 @@
 #include "common/logging.h"
 #include "large_obj.h"
 #include "settings.h"
+#include "fe_utils/cancel.h"
 
 static void print_lo_result(const char *fmt,...) pg_attribute_printf(1, 2);
 
@@ -146,7 +147,7 @@ do_lo_export(const char *loid_arg, const char *filename_arg)
 	if (!start_lo_xact("\\lo_export", &own_transaction))
 		return false;
 
-	SetCancelConn();
+	SetCancelConn(NULL);
 	status = lo_export(pset.db, atooid(loid_arg), filename_arg);
 	ResetCancelConn();
 
@@ -182,7 +183,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
 	if (!start_lo_xact("\\lo_import", &own_transaction))
 		return false;
 
-	SetCancelConn();
+	SetCancelConn(NULL);
 	loid = lo_import(pset.db, filename_arg);
 	ResetCancelConn();
 
@@ -244,7 +245,7 @@ do_lo_unlink(const char *loid_arg)
 	if (!start_lo_xact("\\lo_unlink", &own_transaction))
 		return false;
 
-	SetCancelConn();
+	SetCancelConn(NULL);
 	status = lo_unlink(pset.db, loid);
 	ResetCancelConn();
 
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 0d941ef5ba..43cf139a31 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -301,7 +301,7 @@ main(int argc, char *argv[])
 		exit(EXIT_BADCONN);
 	}
 
-	setup_cancel_handler();
+	psql_setup_cancel_handler();
 
 	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
 
diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c
index d380127356..3aee5f2834 100644
--- a/src/bin/scripts/clusterdb.c
+++ b/src/bin/scripts/clusterdb.c
@@ -133,7 +133,7 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
-	setup_cancel_handler();
+	setup_cancel_handler(NULL);
 
 	if (alldb)
 	{
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index 1b38a1da49..d2a7547441 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -24,14 +24,6 @@
 
 #define ERRCODE_UNDEFINED_TABLE  "42P01"
 
-
-static PGcancel *volatile cancelConn = NULL;
-bool		CancelRequested = false;
-
-#ifdef WIN32
-static CRITICAL_SECTION cancelConnLock;
-#endif
-
 /*
  * Provide strictly harmonized handling of --help and --version
  * options.
@@ -465,142 +457,3 @@ yesno_prompt(const char *question)
 			   _(PG_YESLETTER), _(PG_NOLETTER));
 	}
 }
-
-/*
- * SetCancelConn
- *
- * Set cancelConn to point to the current database connection.
- */
-void
-SetCancelConn(PGconn *conn)
-{
-	PGcancel   *oldCancelConn;
-
-#ifdef WIN32
-	EnterCriticalSection(&cancelConnLock);
-#endif
-
-	/* Free the old one if we have one */
-	oldCancelConn = cancelConn;
-
-	/* be sure handle_sigint doesn't use pointer while freeing */
-	cancelConn = NULL;
-
-	if (oldCancelConn != NULL)
-		PQfreeCancel(oldCancelConn);
-
-	cancelConn = PQgetCancel(conn);
-
-#ifdef WIN32
-	LeaveCriticalSection(&cancelConnLock);
-#endif
-}
-
-/*
- * ResetCancelConn
- *
- * Free the current cancel connection, if any, and set to NULL.
- */
-void
-ResetCancelConn(void)
-{
-	PGcancel   *oldCancelConn;
-
-#ifdef WIN32
-	EnterCriticalSection(&cancelConnLock);
-#endif
-
-	oldCancelConn = cancelConn;
-
-	/* be sure handle_sigint doesn't use pointer while freeing */
-	cancelConn = NULL;
-
-	if (oldCancelConn != NULL)
-		PQfreeCancel(oldCancelConn);
-
-#ifdef WIN32
-	LeaveCriticalSection(&cancelConnLock);
-#endif
-}
-
-#ifndef WIN32
-/*
- * Handle interrupt signals by canceling the current command, if a cancelConn
- * is set.
- */
-static void
-handle_sigint(SIGNAL_ARGS)
-{
-	int			save_errno = errno;
-	char		errbuf[256];
-
-	/* Send QueryCancel if we are processing a database query */
-	if (cancelConn != NULL)
-	{
-		if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
-		{
-			CancelRequested = true;
-			fprintf(stderr, _("Cancel request sent\n"));
-		}
-		else
-			fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
-	}
-	else
-		CancelRequested = true;
-
-	errno = save_errno;			/* just in case the write changed it */
-}
-
-void
-setup_cancel_handler(void)
-{
-	pqsignal(SIGINT, handle_sigint);
-}
-#else							/* WIN32 */
-
-/*
- * Console control handler for Win32. Note that the control handler will
- * execute on a *different thread* than the main one, so we need to do
- * proper locking around those structures.
- */
-static BOOL WINAPI
-consoleHandler(DWORD dwCtrlType)
-{
-	char		errbuf[256];
-
-	if (dwCtrlType == CTRL_C_EVENT ||
-		dwCtrlType == CTRL_BREAK_EVENT)
-	{
-		/* Send QueryCancel if we are processing a database query */
-		EnterCriticalSection(&cancelConnLock);
-		if (cancelConn != NULL)
-		{
-			if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
-			{
-				fprintf(stderr, _("Cancel request sent\n"));
-				CancelRequested = true;
-			}
-			else
-				fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
-		}
-		else
-			CancelRequested = true;
-
-		LeaveCriticalSection(&cancelConnLock);
-
-		return TRUE;
-	}
-	else
-		/* Return FALSE for any signals not being handled */
-		return FALSE;
-}
-
-void
-setup_cancel_handler(void)
-{
-	InitializeCriticalSection(&cancelConnLock);
-
-	SetConsoleCtrlHandler(consoleHandler, TRUE);
-}
-
-#endif							/* WIN32 */
diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h
index f36b26a576..12748258a6 100644
--- a/src/bin/scripts/common.h
+++ b/src/bin/scripts/common.h
@@ -13,6 +13,7 @@
 #include "libpq-fe.h"
 #include "getopt_long.h"		/* pgrminclude ignore */
 #include "pqexpbuffer.h"		/* pgrminclude ignore */
+#include "fe_utils/cancel.h"
 
 enum trivalue
 {
@@ -60,10 +61,4 @@ extern void appendQualifiedRelation(PQExpBuffer buf, const char *name,
 
 extern bool yesno_prompt(const char *question);
 
-extern void setup_cancel_handler(void);
-
-extern void SetCancelConn(PGconn *conn);
-extern void ResetCancelConn(void);
-
-
 #endif							/* COMMON_H */
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index f00aec15de..bedd95cf9d 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -187,7 +187,7 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
-	setup_cancel_handler();
+	setup_cancel_handler(NULL);
 
 	if (alldb)
 	{
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
index 2c7219239f..83a94dc632 100644
--- a/src/bin/scripts/vacuumdb.c
+++ b/src/bin/scripts/vacuumdb.c
@@ -257,7 +257,7 @@ main(int argc, char *argv[])
 		/* allow 'and_analyze' with 'analyze_only' */
 	}
 
-	setup_cancel_handler();
+	setup_cancel_handler(NULL);
 
 	/* Avoid opening extra connections. */
 	if (tbl_count && (concurrentCons > tbl_count))
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index f2e516a2aa..43a5bf5d49 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -20,7 +20,7 @@ include $(top_builddir)/src/Makefile.global
 override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS = conditional.o mbprint.o print.o psqlscan.o recovery_gen.o \
-       simple_list.o string_utils.o
+       simple_list.o string_utils.o cancel.o
 
 all: libpgfeutils.a
 
diff --git a/src/fe_utils/cancel.c b/src/fe_utils/cancel.c
new file mode 100644
index 0000000000..f8a8299fcb
--- /dev/null
+++ b/src/fe_utils/cancel.c
@@ -0,0 +1,194 @@
+/*
+ * interrupt a connection
+ *
+ * Copyright (c) 2000-2019, PostgreSQL Global Development Group
+ *
+ * src/fe-utils/cancel.c
+ */
+
+#include "postgres_fe.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "libpq-fe.h"
+#include "fe_utils/connect.h"
+#include "fe_utils/string_utils.h"
+#include "fe_utils/cancel.h"
+
+/*
+ * Write a simple string to stderr --- must be safe in a signal handler.
+ * We ignore the write() result since there's not much we could do about it.
+ * Certain compilers make that harder than it ought to be.
+ */
+#define write_stderr(str) \
+	do { \
+		const char *str_ = (str); \
+		int		rc_; \
+		rc_ = write(fileno(stderr), str_, strlen(str_)); \
+		(void) rc_; \
+	} while (0)
+
+static PGcancel *volatile cancelConn = NULL;
+bool		CancelRequested = false;
+
+#ifdef WIN32
+static CRITICAL_SECTION cancelConnLock;
+#endif
+
+/*
+ * SetCancelConn
+ *
+ * Set cancelConn to point to the current database connection.
+ */
+void
+SetCancelConn(PGconn *conn)
+{
+	PGcancel   *oldCancelConn;
+
+#ifdef WIN32
+	EnterCriticalSection(&cancelConnLock);
+#endif
+
+	/* Free the old one if we have one */
+	oldCancelConn = cancelConn;
+	/* be sure handle_sigint doesn't use pointer while freeing */
+	cancelConn = NULL;
+
+	if (oldCancelConn != NULL)
+		PQfreeCancel(oldCancelConn);
+
+	cancelConn = PQgetCancel(conn);
+
+#ifdef WIN32
+	LeaveCriticalSection(&cancelConnLock);
+#endif
+}
+
+
+/*
+ * ResetCancelConn
+ *
+ * Free the current cancel connection, if any, and set to NULL.
+ */
+void
+ResetCancelConn(void)
+{
+	PGcancel   *oldCancelConn;
+
+#ifdef WIN32
+	EnterCriticalSection(&cancelConnLock);
+#endif
+
+	oldCancelConn = cancelConn;
+	/* be sure handle_sigint doesn't use pointer while freeing */
+	cancelConn = NULL;
+
+	if (oldCancelConn != NULL)
+		PQfreeCancel(oldCancelConn);
+
+#ifdef WIN32
+	LeaveCriticalSection(&cancelConnLock);
+#endif
+}
+
+#ifndef WIN32
+/*
+ * Additional callback to handle interrupts
+ */
+static void (*sigint_callback)(void) = NULL;
+
+/*
+ * Handle interrupt signals by canceling the current command, if a cancelConn
+ * is set.
+ */
+static void
+handle_sigint(SIGNAL_ARGS)
+{
+	int			save_errno = errno;
+	char		errbuf[256];
+
+	if (sigint_callback != NULL)
+		sigint_callback();
+
+	/* Send QueryCancel if we are processing a database query */
+	if (cancelConn != NULL)
+	{
+		if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
+		{
+			CancelRequested = true;
+			write_stderr(_("Cancel request sent\n"));
+		}
+		else
+		{
+			write_stderr(_("Could not send cancel request: "));
+			write_stderr(errbuf);
+		}
+	}
+	else
+		CancelRequested = true;
+
+	errno = save_errno;			/* just in case the write changed it */
+}
+
+void
+setup_cancel_handler(void (*callback)(void))
+{
+	sigint_callback = callback;
+	pqsignal(SIGINT, handle_sigint);
+	/* what about SIGTERM? SIGQUIT? */
+}
+
+#else							/* WIN32 */
+
+/*
+ * Console control handler for Win32. Note that the control handler will
+ * execute on a *different thread* than the main one, so we need to do
+ * proper locking around those structures.
+ */
+static BOOL WINAPI
+consoleHandler(DWORD dwCtrlType)
+{
+	char		errbuf[256];
+
+	if (dwCtrlType == CTRL_C_EVENT ||
+		dwCtrlType == CTRL_BREAK_EVENT)
+	{
+		/* Send QueryCancel if we are processing a database query */
+		EnterCriticalSection(&cancelConnLock);
+		if (cancelConn != NULL)
+		{
+			if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
+			{
+				write_stderr(_("Cancel request sent\n"));
+				CancelRequested = true;
+			}
+			else
+			{
+				write_stderr(_("Could not send cancel request: %s"));
+				write_stderr(errbuf);
+			}
+		}
+		else
+			CancelRequested = true;
+
+		LeaveCriticalSection(&cancelConnLock);
+
+		return TRUE;
+	}
+	else
+		/* Return FALSE for any signals not being handled */
+		return FALSE;
+}
+
+void
+setup_cancel_handler(void *ignored)
+{
+	Assert(ignored == NULL);
+
+	InitializeCriticalSection(&cancelConnLock);
+
+	SetConsoleCtrlHandler(consoleHandler, TRUE);
+}
+
+#endif							/* WIN32 */
diff --git a/src/include/fe_utils/cancel.h b/src/include/fe_utils/cancel.h
new file mode 100644
index 0000000000..686d7c9dc4
--- /dev/null
+++ b/src/include/fe_utils/cancel.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * Query Cancelation
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/cancel.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CANCEL_H
+#define CANCEL_H
+
+extern void SetCancelConn(PGconn *conn);
+extern void ResetCancelConn(void);
+extern bool CancelRequested;
+
+#ifndef WIN32
+extern void setup_cancel_handler(void (*callback)(void));
+#else
+/*
+ * Ensure that the signature is the same under windows, at the price of
+ * an ignored function parameter.
+ */
+extern void setup_cancel_handler(void *ignored);
+#endif /* WIN32 */
+
+#endif /* CANCEL_H */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 7a103e6140..e6e04a7ea6 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -143,7 +143,7 @@ sub mkvcbuild
 
 	our @pgfeutilsfiles = qw(
 	  conditional.c mbprint.c print.c psqlscan.l psqlscan.c
-	  simple_list.c string_utils.c recovery_gen.c);
+	  simple_list.c string_utils.c recovery_gen.c cancel.c);
 
 	$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
 	$libpgport->AddDefine('FRONTEND');

Reply via email to