~ubuntu-branches/ubuntu/precise/postgresql-9.1/precise-security

« back to all changes in this revision

Viewing changes to src/backend/postmaster/fork_process.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * fork_process.c
 
3
 *       A simple wrapper on top of fork(). This does not handle the
 
4
 *       EXEC_BACKEND case; it might be extended to do so, but it would be
 
5
 *       considerably more complex.
 
6
 *
 
7
 * Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        src/backend/postmaster/fork_process.c
 
11
 */
 
12
#include "postgres.h"
 
13
#include "postmaster/fork_process.h"
 
14
 
 
15
#include <fcntl.h>
 
16
#include <time.h>
 
17
#include <sys/stat.h>
 
18
#include <sys/time.h>
 
19
#include <unistd.h>
 
20
 
 
21
#ifndef WIN32
 
22
/*
 
23
 * Wrapper for fork(). Return values are the same as those for fork():
 
24
 * -1 if the fork failed, 0 in the child process, and the PID of the
 
25
 * child in the parent process.
 
26
 */
 
27
pid_t
 
28
fork_process(void)
 
29
{
 
30
        pid_t           result;
 
31
 
 
32
#ifdef LINUX_PROFILE
 
33
        struct itimerval prof_itimer;
 
34
#endif
 
35
 
 
36
        /*
 
37
         * Flush stdio channels just before fork, to avoid double-output problems.
 
38
         * Ideally we'd use fflush(NULL) here, but there are still a few non-ANSI
 
39
         * stdio libraries out there (like SunOS 4.1.x) that coredump if we do.
 
40
         * Presently stdout and stderr are the only stdio output channels used by
 
41
         * the postmaster, so fflush'ing them should be sufficient.
 
42
         */
 
43
        fflush(stdout);
 
44
        fflush(stderr);
 
45
 
 
46
#ifdef LINUX_PROFILE
 
47
 
 
48
        /*
 
49
         * Linux's fork() resets the profiling timer in the child process. If we
 
50
         * want to profile child processes then we need to save and restore the
 
51
         * timer setting.  This is a waste of time if not profiling, however, so
 
52
         * only do it if commanded by specific -DLINUX_PROFILE switch.
 
53
         */
 
54
        getitimer(ITIMER_PROF, &prof_itimer);
 
55
#endif
 
56
 
 
57
        result = fork();
 
58
        if (result == 0)
 
59
        {
 
60
                /* fork succeeded, in child */
 
61
#ifdef LINUX_PROFILE
 
62
                setitimer(ITIMER_PROF, &prof_itimer, NULL);
 
63
#endif
 
64
 
 
65
                /*
 
66
                 * By default, Linux tends to kill the postmaster in out-of-memory
 
67
                 * situations, because it blames the postmaster for the sum of child
 
68
                 * process sizes *including shared memory*.  (This is unbelievably
 
69
                 * stupid, but the kernel hackers seem uninterested in improving it.)
 
70
                 * Therefore it's often a good idea to protect the postmaster by
 
71
                 * setting its oom_adj value negative (which has to be done in a
 
72
                 * root-owned startup script).  If you just do that much, all child
 
73
                 * processes will also be protected against OOM kill, which might not
 
74
                 * be desirable.  You can then choose to build with LINUX_OOM_ADJ
 
75
                 * #defined to 0, or some other value that you want child processes to
 
76
                 * adopt here.
 
77
                 */
 
78
#ifdef LINUX_OOM_ADJ
 
79
                {
 
80
                        /*
 
81
                         * Use open() not stdio, to ensure we control the open flags. Some
 
82
                         * Linux security environments reject anything but O_WRONLY.
 
83
                         */
 
84
                        int                     fd = open("/proc/self/oom_adj", O_WRONLY, 0);
 
85
 
 
86
                        /* We ignore all errors */
 
87
                        if (fd >= 0)
 
88
                        {
 
89
                                char            buf[16];
 
90
 
 
91
                                snprintf(buf, sizeof(buf), "%d\n", LINUX_OOM_ADJ);
 
92
                                (void) write(fd, buf, strlen(buf));
 
93
                                close(fd);
 
94
                        }
 
95
                }
 
96
#endif   /* LINUX_OOM_ADJ */
 
97
        }
 
98
 
 
99
        return result;
 
100
}
 
101
 
 
102
#endif   /* ! WIN32 */