summaryrefslogtreecommitdiffstats
path: root/src/backend/postmaster/fork_process.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
commit311bcfc6b3acdd6fd152798c7f287ddf74fa2a98 (patch)
tree0ec307299b1dada3701e42f4ca6eda57d708261e /src/backend/postmaster/fork_process.c
parentInitial commit. (diff)
downloadpostgresql-15-upstream.tar.xz
postgresql-15-upstream.zip
Adding upstream version 15.4.upstream/15.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/postmaster/fork_process.c')
-rw-r--r--src/backend/postmaster/fork_process.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c
new file mode 100644
index 0000000..c75be03
--- /dev/null
+++ b/src/backend/postmaster/fork_process.c
@@ -0,0 +1,115 @@
+/*
+ * fork_process.c
+ * A simple wrapper on top of fork(). This does not handle the
+ * EXEC_BACKEND case; it might be extended to do so, but it would be
+ * considerably more complex.
+ *
+ * Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/postmaster/fork_process.c
+ */
+#include "postgres.h"
+
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "postmaster/fork_process.h"
+
+#ifndef WIN32
+/*
+ * Wrapper for fork(). Return values are the same as those for fork():
+ * -1 if the fork failed, 0 in the child process, and the PID of the
+ * child in the parent process.
+ */
+pid_t
+fork_process(void)
+{
+ pid_t result;
+ const char *oomfilename;
+
+#ifdef LINUX_PROFILE
+ struct itimerval prof_itimer;
+#endif
+
+ /*
+ * Flush stdio channels just before fork, to avoid double-output problems.
+ * Ideally we'd use fflush(NULL) here, but there are still a few non-ANSI
+ * stdio libraries out there (like SunOS 4.1.x) that coredump if we do.
+ * Presently stdout and stderr are the only stdio output channels used by
+ * the postmaster, so fflush'ing them should be sufficient.
+ */
+ fflush(stdout);
+ fflush(stderr);
+
+#ifdef LINUX_PROFILE
+
+ /*
+ * Linux's fork() resets the profiling timer in the child process. If we
+ * want to profile child processes then we need to save and restore the
+ * timer setting. This is a waste of time if not profiling, however, so
+ * only do it if commanded by specific -DLINUX_PROFILE switch.
+ */
+ getitimer(ITIMER_PROF, &prof_itimer);
+#endif
+
+ result = fork();
+ if (result == 0)
+ {
+ /* fork succeeded, in child */
+#ifdef LINUX_PROFILE
+ setitimer(ITIMER_PROF, &prof_itimer, NULL);
+#endif
+
+ /*
+ * By default, Linux tends to kill the postmaster in out-of-memory
+ * situations, because it blames the postmaster for the sum of child
+ * process sizes *including shared memory*. (This is unbelievably
+ * stupid, but the kernel hackers seem uninterested in improving it.)
+ * Therefore it's often a good idea to protect the postmaster by
+ * setting its OOM score adjustment negative (which has to be done in
+ * a root-owned startup script). Since the adjustment is inherited by
+ * child processes, this would ordinarily mean that all the
+ * postmaster's children are equally protected against OOM kill, which
+ * is not such a good idea. So we provide this code to allow the
+ * children to change their OOM score adjustments again. Both the
+ * file name to write to and the value to write are controlled by
+ * environment variables, which can be set by the same startup script
+ * that did the original adjustment.
+ */
+ oomfilename = getenv("PG_OOM_ADJUST_FILE");
+
+ if (oomfilename != NULL)
+ {
+ /*
+ * Use open() not stdio, to ensure we control the open flags. Some
+ * Linux security environments reject anything but O_WRONLY.
+ */
+ int fd = open(oomfilename, O_WRONLY, 0);
+
+ /* We ignore all errors */
+ if (fd >= 0)
+ {
+ const char *oomvalue = getenv("PG_OOM_ADJUST_VALUE");
+ int rc;
+
+ if (oomvalue == NULL) /* supply a useful default */
+ oomvalue = "0";
+
+ rc = write(fd, oomvalue, strlen(oomvalue));
+ (void) rc;
+ close(fd);
+ }
+ }
+
+ /* do post-fork initialization for random number generation */
+ pg_strong_random_init();
+ }
+
+ return result;
+}
+
+#endif /* ! WIN32 */