v33-0001-Moving-exit_nicely-and-fatal-into-fe_utils.patch
application/octet-stream
Filename: v33-0001-Moving-exit_nicely-and-fatal-into-fe_utils.patch
Type: application/octet-stream
Part: 0
Message:
Re: new heapcheck contrib module
Patch
Format: format-patch
Series: patch v33-0001
Subject: Moving exit_nicely and fatal into fe_utils
| File | + | − |
|---|---|---|
| src/bin/pg_dump/parallel.c | 16 | 0 |
| src/bin/pg_dump/parallel.h | 0 | 5 |
| src/bin/pg_dump/pg_backup_archiver.h | 1 | 0 |
| src/bin/pg_dump/pg_backup_utils.c | 0 | 59 |
| src/bin/pg_dump/pg_backup_utils.h | 0 | 8 |
| src/fe_utils/exit_utils.c | 105 | 0 |
| src/fe_utils/Makefile | 1 | 0 |
| src/include/fe_utils/exit_utils.h | 26 | 0 |
| src/tools/msvc/Mkvcbuild.pm | 1 | 1 |
From 9f5dddb330f7a5bec9a2233df7ad2d4e269ffc55 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Mon, 11 Jan 2021 16:04:31 -0800
Subject: [PATCH v33 1/8] Moving exit_nicely and fatal into fe_utils
Various frontend executables in src/bin, src/bin/scripts, and
contrib/ have logic for logging and exiting under error conditions.
The logging code itself is already under common/, but executables
differ in their calls to exit() vs. exit_nicely(), with
exit_nicely() not uniformly defined, and sometimes all of this
wrapped up under a macro named fatal(), the definition of that macro
also not uniformly defined. This makes it harder to move code out
of these executables into a shared library under fe_utils/.
Standardizing all executables to define these things the same way or
to use a single fe_utils/ library is beyond the scope of this patch,
but this patch should get the ball rolling in that direction.
For pg_amcheck purposes, we really just need to get scripts_parallel
moved into fe_utils, which doesn't require changing pg_dump at all.
But by creating a new fe_utils/exit_utils which is compatible with
pg_dump along with everything else, we avoid creating yet another
compatibility problem. So we move the functions "on_exit_nicely"
and "exit_nicely", and the macro "fatal" from pg_dump into fe_utils,
and we refactor the on_exit_nicely() implementation to no longer
contain pg_dump specific logic for exiting threads on Windows.
Instead, we create a new on_exit_nicely_final() function for
registering a final callback, and use that from within pg_dump to
register a final callback encapsulating knowledge of threading
variables.
The on_exit_nicely_final() function, and associated
final_on_exit_nicely variable, are not strictly necessary. The same
behavior could be achieved by registering an exiting callback via
the on_exit_nicely() function prior to any other callbacks, but that
would place a larger burden on scripts authors to make certain that
(a) no other callback gets registered before the exiting callback,
and (b) that only one exiting callback gets registered.
---
src/bin/pg_dump/parallel.c | 16 ++++
src/bin/pg_dump/parallel.h | 5 --
src/bin/pg_dump/pg_backup_archiver.h | 1 +
src/bin/pg_dump/pg_backup_utils.c | 59 ---------------
src/bin/pg_dump/pg_backup_utils.h | 8 --
src/fe_utils/Makefile | 1 +
src/fe_utils/exit_utils.c | 105 +++++++++++++++++++++++++++
src/include/fe_utils/exit_utils.h | 26 +++++++
src/tools/msvc/Mkvcbuild.pm | 2 +-
9 files changed, 150 insertions(+), 73 deletions(-)
create mode 100644 src/fe_utils/exit_utils.c
create mode 100644 src/include/fe_utils/exit_utils.h
diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c
index c7351a43fd..e619f126f5 100644
--- a/src/bin/pg_dump/parallel.c
+++ b/src/bin/pg_dump/parallel.c
@@ -228,6 +228,19 @@ static char *readMessageFromPipe(int fd);
#define messageStartsWith(msg, prefix) \
(strncmp(msg, prefix, strlen(prefix)) == 0)
+#ifdef WIN32
+
+/*
+ * An on_exit_nicely_callback which, if run in a parallel worker thread on
+ * Windows, will only exit the thread, not the whole process.
+ */
+static void
+end_threads(int code, void *arg)
+{
+ if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
+ _endthreadex(code);
+}
+#endif
/*
* Initialize parallel dump support --- should be called early in process
@@ -255,6 +268,9 @@ init_parallel_dump_utils(void)
exit_nicely(1);
}
+ /* install callback to close threads on exit */
+ on_exit_nicely_final(end_threads, NULL);
+
parallel_init_done = true;
}
#endif
diff --git a/src/bin/pg_dump/parallel.h b/src/bin/pg_dump/parallel.h
index 0fbf736c81..48c48e12e6 100644
--- a/src/bin/pg_dump/parallel.h
+++ b/src/bin/pg_dump/parallel.h
@@ -45,11 +45,6 @@ typedef struct ParallelState
ParallelSlot *parallelSlot; /* private info about each worker */
} ParallelState;
-#ifdef WIN32
-extern bool parallel_init_done;
-extern DWORD mainThreadId;
-#endif
-
extern void init_parallel_dump_utils(void);
extern bool IsEveryWorkerIdle(ParallelState *pstate);
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index a8ea5c7eae..37d157b7ad 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -26,6 +26,7 @@
#include <time.h>
+#include "fe_utils/exit_utils.h"
#include "libpq-fe.h"
#include "pg_backup.h"
#include "pqexpbuffer.h"
diff --git a/src/bin/pg_dump/pg_backup_utils.c b/src/bin/pg_dump/pg_backup_utils.c
index c709a40e06..631e88f7db 100644
--- a/src/bin/pg_dump/pg_backup_utils.c
+++ b/src/bin/pg_dump/pg_backup_utils.c
@@ -19,16 +19,6 @@
/* Globals exported by this file */
const char *progname = NULL;
-#define MAX_ON_EXIT_NICELY 20
-
-static struct
-{
- on_exit_nicely_callback function;
- void *arg;
-} on_exit_nicely_list[MAX_ON_EXIT_NICELY];
-
-static int on_exit_nicely_index;
-
/*
* Parse a --section=foo command line argument.
*
@@ -57,52 +47,3 @@ set_dump_section(const char *arg, int *dumpSections)
exit_nicely(1);
}
}
-
-
-/* Register a callback to be run when exit_nicely is invoked. */
-void
-on_exit_nicely(on_exit_nicely_callback function, void *arg)
-{
- if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
- {
- pg_log_fatal("out of on_exit_nicely slots");
- exit_nicely(1);
- }
- on_exit_nicely_list[on_exit_nicely_index].function = function;
- on_exit_nicely_list[on_exit_nicely_index].arg = arg;
- on_exit_nicely_index++;
-}
-
-/*
- * Run accumulated on_exit_nicely callbacks in reverse order and then exit
- * without printing any message.
- *
- * If running in a parallel worker thread on Windows, we only exit the thread,
- * not the whole process.
- *
- * Note that in parallel operation on Windows, the callback(s) will be run
- * by each thread since the list state is necessarily shared by all threads;
- * each callback must contain logic to ensure it does only what's appropriate
- * for its thread. On Unix, callbacks are also run by each process, but only
- * for callbacks established before we fork off the child processes. (It'd
- * be cleaner to reset the list after fork(), and let each child establish
- * its own callbacks; but then the behavior would be completely inconsistent
- * between Windows and Unix. For now, just be sure to establish callbacks
- * before forking to avoid inconsistency.)
- */
-void
-exit_nicely(int code)
-{
- int i;
-
- for (i = on_exit_nicely_index - 1; i >= 0; i--)
- on_exit_nicely_list[i].function(code,
- on_exit_nicely_list[i].arg);
-
-#ifdef WIN32
- if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
- _endthreadex(code);
-#endif
-
- exit(code);
-}
diff --git a/src/bin/pg_dump/pg_backup_utils.h b/src/bin/pg_dump/pg_backup_utils.h
index 306798f9ac..ee4409c274 100644
--- a/src/bin/pg_dump/pg_backup_utils.h
+++ b/src/bin/pg_dump/pg_backup_utils.h
@@ -15,22 +15,14 @@
#ifndef PG_BACKUP_UTILS_H
#define PG_BACKUP_UTILS_H
-#include "common/logging.h"
-
/* bits returned by set_dump_section */
#define DUMP_PRE_DATA 0x01
#define DUMP_DATA 0x02
#define DUMP_POST_DATA 0x04
#define DUMP_UNSECTIONED 0xff
-typedef void (*on_exit_nicely_callback) (int code, void *arg);
-
extern const char *progname;
extern void set_dump_section(const char *arg, int *dumpSections);
-extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
-extern void exit_nicely(int code) pg_attribute_noreturn();
-
-#define fatal(...) do { pg_log_error(__VA_ARGS__); exit_nicely(1); } while(0)
#endif /* PG_BACKUP_UTILS_H */
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index 10d6838cf9..d6c328faf1 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -23,6 +23,7 @@ OBJS = \
archive.o \
cancel.o \
conditional.o \
+ exit_utils.o \
mbprint.o \
print.o \
psqlscan.o \
diff --git a/src/fe_utils/exit_utils.c b/src/fe_utils/exit_utils.c
new file mode 100644
index 0000000000..8c2760a78c
--- /dev/null
+++ b/src/fe_utils/exit_utils.c
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ *
+ * Exiting with cleanup callback facilities for frontend code
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/fe_utils/exit_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "fe_utils/exit_utils.h"
+
+#define MAX_ON_EXIT_NICELY 20
+
+typedef struct
+{
+ on_exit_nicely_callback function;
+ void *arg;
+} OnExitCallback;
+
+/*
+ * Storage for registered on_exit_nicely_callbacks to be run by exit_nicely()
+ * before exit()ing. The callbacks in the on_exit_nicely_list[] are run in
+ * reverse of the order that they were registered. The final_on_exit_nicely
+ * callback is run after all the ones from the list, regardless of when it was
+ * registered.
+ *
+ * Note that in parallel operation on Windows, the callback(s) will be run
+ * by each thread since the list state is necessarily shared by all
+ * threads; each callback must contain logic to ensure it does only what's
+ * appropriate for its thread. On Unix, callbacks are also run by each
+ * process, but only for callbacks established before we fork off the child
+ * processes. (It'd be cleaner to reset the list after fork(), and let
+ * each child establish its own callbacks; but then the behavior would be
+ * completely inconsistent between Windows and Unix. For now, just be sure
+ * to establish callbacks before forking to avoid inconsistency.)
+ */
+static OnExitCallback final_on_exit_nicely;
+static OnExitCallback on_exit_nicely_list[MAX_ON_EXIT_NICELY];
+static int on_exit_nicely_index;
+
+/*
+ * Register a callback to be run when exit_nicely is invoked.
+ *
+ * If you wish to register a callback which itself exits the application or
+ * thread, see on_exit_nicely_final() instead.
+ */
+void
+on_exit_nicely(on_exit_nicely_callback function, void *arg)
+{
+ if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
+ {
+ pg_log_fatal("out of on_exit_nicely slots");
+ exit_nicely(1);
+ }
+ on_exit_nicely_list[on_exit_nicely_index].function = function;
+ on_exit_nicely_list[on_exit_nicely_index].arg = arg;
+ on_exit_nicely_index++;
+}
+
+/*
+ * Register a final callback to be run after all other on_exit_nicely callbacks
+ * have been processed.
+ *
+ * Only one final callback may be registered. Attempts to subsequently register
+ * additional final callbacks are an error.
+ *
+ * A callback registered via on_exit_nicely_final() may choose to exit the
+ * application or thread without risk of skipping any other callback logic. If
+ * the callback does not itself exit, exit_nicely() will exit() immediately
+ * after the final callback returns.
+ */
+void
+on_exit_nicely_final(on_exit_nicely_callback function, void *arg)
+{
+ if (final_on_exit_nicely.function)
+ {
+ pg_log_fatal("multiple on_exit_nicely_final callbacks");
+ exit_nicely(1);
+ }
+ final_on_exit_nicely.function = function;
+ final_on_exit_nicely.arg = arg;
+}
+
+/*
+ * Run accumulated on_exit_nicely callbacks in reverse order followed by the
+ * final on_exit_nicely callback, if any, and then exit() without printing any
+ * message.
+ */
+void
+exit_nicely(int code)
+{
+ int i;
+
+ for (i = on_exit_nicely_index - 1; i >= 0; i--)
+ on_exit_nicely_list[i].function(code,
+ on_exit_nicely_list[i].arg);
+
+ if (final_on_exit_nicely.function)
+ final_on_exit_nicely.function(code, final_on_exit_nicely.arg);
+
+ exit(code);
+}
diff --git a/src/include/fe_utils/exit_utils.h b/src/include/fe_utils/exit_utils.h
new file mode 100644
index 0000000000..6326404133
--- /dev/null
+++ b/src/include/fe_utils/exit_utils.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * Exiting with cleanup callback facilities for frontend code
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/exit_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXIT_UTILS_H
+#define EXIT_UTILS_H
+
+#include "postgres_fe.h"
+#include "common/logging.h"
+
+typedef void (*on_exit_nicely_callback) (int code, void *arg);
+
+extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
+extern void on_exit_nicely_final(on_exit_nicely_callback function, void *arg);
+extern void exit_nicely(int code) pg_attribute_noreturn();
+
+#define fatal(...) do { pg_log_error(__VA_ARGS__); exit_nicely(1); } while(0)
+
+#endif /* EXIT_UTILS_H */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 7213e65e08..0c6c1c996f 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -147,7 +147,7 @@ sub mkvcbuild
our @pgcommonbkndfiles = @pgcommonallfiles;
our @pgfeutilsfiles = qw(
- archive.c cancel.c conditional.c mbprint.c print.c psqlscan.l
+ archive.c cancel.c conditional.c exit_utils.c mbprint.c print.c psqlscan.l
psqlscan.c simple_list.c string_utils.c recovery_gen.c);
$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
--
2.21.1 (Apple Git-122.3)