Header And Logo

PostgreSQL
| The world's most advanced open source database.

fork_process.c

Go to the documentation of this file.
00001 /*
00002  * fork_process.c
00003  *   A simple wrapper on top of fork(). This does not handle the
00004  *   EXEC_BACKEND case; it might be extended to do so, but it would be
00005  *   considerably more complex.
00006  *
00007  * Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  *
00009  * IDENTIFICATION
00010  *    src/backend/postmaster/fork_process.c
00011  */
00012 #include "postgres.h"
00013 #include "postmaster/fork_process.h"
00014 
00015 #include <fcntl.h>
00016 #include <time.h>
00017 #include <sys/stat.h>
00018 #include <sys/time.h>
00019 #include <unistd.h>
00020 #ifdef USE_SSL
00021 #include <openssl/rand.h>
00022 #endif
00023 
00024 #ifndef WIN32
00025 /*
00026  * Wrapper for fork(). Return values are the same as those for fork():
00027  * -1 if the fork failed, 0 in the child process, and the PID of the
00028  * child in the parent process.
00029  */
00030 pid_t
00031 fork_process(void)
00032 {
00033     pid_t       result;
00034 
00035 #ifdef LINUX_PROFILE
00036     struct itimerval prof_itimer;
00037 #endif
00038 
00039     /*
00040      * Flush stdio channels just before fork, to avoid double-output problems.
00041      * Ideally we'd use fflush(NULL) here, but there are still a few non-ANSI
00042      * stdio libraries out there (like SunOS 4.1.x) that coredump if we do.
00043      * Presently stdout and stderr are the only stdio output channels used by
00044      * the postmaster, so fflush'ing them should be sufficient.
00045      */
00046     fflush(stdout);
00047     fflush(stderr);
00048 
00049 #ifdef LINUX_PROFILE
00050 
00051     /*
00052      * Linux's fork() resets the profiling timer in the child process. If we
00053      * want to profile child processes then we need to save and restore the
00054      * timer setting.  This is a waste of time if not profiling, however, so
00055      * only do it if commanded by specific -DLINUX_PROFILE switch.
00056      */
00057     getitimer(ITIMER_PROF, &prof_itimer);
00058 #endif
00059 
00060     result = fork();
00061     if (result == 0)
00062     {
00063         /* fork succeeded, in child */
00064 #ifdef LINUX_PROFILE
00065         setitimer(ITIMER_PROF, &prof_itimer, NULL);
00066 #endif
00067 
00068         /*
00069          * By default, Linux tends to kill the postmaster in out-of-memory
00070          * situations, because it blames the postmaster for the sum of child
00071          * process sizes *including shared memory*.  (This is unbelievably
00072          * stupid, but the kernel hackers seem uninterested in improving it.)
00073          * Therefore it's often a good idea to protect the postmaster by
00074          * setting its oom_score_adj value negative (which has to be done in a
00075          * root-owned startup script). If you just do that much, all child
00076          * processes will also be protected against OOM kill, which might not
00077          * be desirable.  You can then choose to build with
00078          * LINUX_OOM_SCORE_ADJ #defined to 0, or to some other value that you
00079          * want child processes to adopt here.
00080          */
00081 #ifdef LINUX_OOM_SCORE_ADJ
00082         {
00083             /*
00084              * Use open() not stdio, to ensure we control the open flags. Some
00085              * Linux security environments reject anything but O_WRONLY.
00086              */
00087             int         fd = open("/proc/self/oom_score_adj", O_WRONLY, 0);
00088 
00089             /* We ignore all errors */
00090             if (fd >= 0)
00091             {
00092                 char        buf[16];
00093                 int         rc;
00094 
00095                 snprintf(buf, sizeof(buf), "%d\n", LINUX_OOM_SCORE_ADJ);
00096                 rc = write(fd, buf, strlen(buf));
00097                 (void) rc;
00098                 close(fd);
00099             }
00100         }
00101 #endif   /* LINUX_OOM_SCORE_ADJ */
00102 
00103         /*
00104          * Older Linux kernels have oom_adj not oom_score_adj.  This works
00105          * similarly except with a different scale of adjustment values.
00106          * If it's necessary to build Postgres to work with either API,
00107          * you can define both LINUX_OOM_SCORE_ADJ and LINUX_OOM_ADJ.
00108          */
00109 #ifdef LINUX_OOM_ADJ
00110         {
00111             /*
00112              * Use open() not stdio, to ensure we control the open flags. Some
00113              * Linux security environments reject anything but O_WRONLY.
00114              */
00115             int         fd = open("/proc/self/oom_adj", O_WRONLY, 0);
00116 
00117             /* We ignore all errors */
00118             if (fd >= 0)
00119             {
00120                 char        buf[16];
00121                 int         rc;
00122 
00123                 snprintf(buf, sizeof(buf), "%d\n", LINUX_OOM_ADJ);
00124                 rc = write(fd, buf, strlen(buf));
00125                 (void) rc;
00126                 close(fd);
00127             }
00128         }
00129 #endif   /* LINUX_OOM_ADJ */
00130 
00131         /*
00132          * Make sure processes do not share OpenSSL randomness state.
00133          */
00134 #ifdef USE_SSL
00135         RAND_cleanup();
00136 #endif
00137     }
00138 
00139     return result;
00140 }
00141 
00142 #endif   /* ! WIN32 */