mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 16:21:30 +03:00
More than twenty years ago (79fcde48b), we hacked the postmaster to avoid a core-dump on systems that didn't support fflush(NULL). We've mostly, though not completely, hewed to that rule ever since. But such systems are surely gone in the wild, so in the spirit of cleaning out no-longer-needed portability hacks let's get rid of multiple per-file fflush() calls in favor of using fflush(NULL). Also, we were fairly inconsistent about whether to fflush() before popen() and system() calls. While we've received no bug reports about that, it seems likely that at least some of these call sites are at risk of odd behavior, such as error messages appearing in an unexpected order. Rather than expend a lot of brain cells figuring out which places are at hazard, let's just establish a uniform coding rule that we should fflush(NULL) before these calls. A no-op fflush() is surely of trivial cost compared to launching a sub-process via a shell; while if it's not a no-op then we likely need it. Discussion: https://postgr.es/m/2923412.1661722825@sss.pgh.pa.us
111 lines
3.0 KiB
C
111 lines
3.0 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
fflush(NULL);
|
|
|
|
#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 */
|