LCOV - code coverage report
Current view: top level - src/backend/postmaster - launch_backend.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 11 13 84.6 %
Date: 2024-05-02 11:11:27 Functions: 1 2 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * launch_backend.c
       4             :  *    Functions for launching backends and other postmaster child
       5             :  *    processes.
       6             :  *
       7             :  * On Unix systems, a new child process is launched with fork().  It inherits
       8             :  * all the global variables and data structures that had been initialized in
       9             :  * the postmaster.  After forking, the child process closes the file
      10             :  * descriptors that are not needed in the child process, and sets up the
      11             :  * mechanism to detect death of the parent postmaster process, etc.  After
      12             :  * that, it calls the right Main function depending on the kind of child
      13             :  * process.
      14             :  *
      15             :  * In EXEC_BACKEND mode, which is used on Windows but can be enabled on other
      16             :  * platforms for testing, the child process is launched by fork() + exec() (or
      17             :  * CreateProcess() on Windows).  It does not inherit the state from the
      18             :  * postmaster, so it needs to re-attach to the shared memory, re-initialize
      19             :  * global variables, reload the config file etc. to get the process to the
      20             :  * same state as after fork() on a Unix system.
      21             :  *
      22             :  *
      23             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      24             :  * Portions Copyright (c) 1994, Regents of the University of California
      25             :  *
      26             :  * IDENTIFICATION
      27             :  *    src/backend/postmaster/launch_backend.c
      28             :  *
      29             :  *-------------------------------------------------------------------------
      30             :  */
      31             : 
      32             : #include "postgres.h"
      33             : 
      34             : #include <unistd.h>
      35             : 
      36             : #include "access/xlog.h"
      37             : #include "common/file_utils.h"
      38             : #include "libpq/libpq-be.h"
      39             : #include "libpq/pqsignal.h"
      40             : #include "miscadmin.h"
      41             : #include "nodes/queryjumble.h"
      42             : #include "port.h"
      43             : #include "postmaster/autovacuum.h"
      44             : #include "postmaster/auxprocess.h"
      45             : #include "postmaster/bgworker_internals.h"
      46             : #include "postmaster/bgwriter.h"
      47             : #include "postmaster/fork_process.h"
      48             : #include "postmaster/pgarch.h"
      49             : #include "postmaster/postmaster.h"
      50             : #include "postmaster/startup.h"
      51             : #include "postmaster/syslogger.h"
      52             : #include "postmaster/walsummarizer.h"
      53             : #include "postmaster/walwriter.h"
      54             : #include "replication/slotsync.h"
      55             : #include "replication/walreceiver.h"
      56             : #include "storage/fd.h"
      57             : #include "storage/ipc.h"
      58             : #include "storage/pg_shmem.h"
      59             : #include "storage/pmsignal.h"
      60             : #include "storage/proc.h"
      61             : #include "tcop/backend_startup.h"
      62             : #include "tcop/tcopprot.h"
      63             : #include "utils/builtins.h"
      64             : #include "utils/datetime.h"
      65             : #include "utils/guc.h"
      66             : #include "utils/memutils.h"
      67             : #include "utils/timestamp.h"
      68             : 
      69             : #ifdef EXEC_BACKEND
      70             : #include "nodes/queryjumble.h"
      71             : #include "storage/pg_shmem.h"
      72             : #include "storage/spin.h"
      73             : #endif
      74             : 
      75             : 
      76             : #ifdef EXEC_BACKEND
      77             : 
      78             : /* Type for a socket that can be inherited to a client process */
      79             : #ifdef WIN32
      80             : typedef struct
      81             : {
      82             :     SOCKET      origsocket;     /* Original socket value, or PGINVALID_SOCKET
      83             :                                  * if not a socket */
      84             :     WSAPROTOCOL_INFO wsainfo;
      85             : } InheritableSocket;
      86             : #else
      87             : typedef int InheritableSocket;
      88             : #endif
      89             : 
      90             : /*
      91             :  * Structure contains all variables passed to exec:ed backends
      92             :  */
      93             : typedef struct
      94             : {
      95             :     char        DataDir[MAXPGPATH];
      96             :     int32       MyCancelKey;
      97             :     int         MyPMChildSlot;
      98             : #ifndef WIN32
      99             :     unsigned long UsedShmemSegID;
     100             : #else
     101             :     void       *ShmemProtectiveRegion;
     102             :     HANDLE      UsedShmemSegID;
     103             : #endif
     104             :     void       *UsedShmemSegAddr;
     105             :     slock_t    *ShmemLock;
     106             :     struct bkend *ShmemBackendArray;
     107             : #ifndef HAVE_SPINLOCKS
     108             :     PGSemaphore *SpinlockSemaArray;
     109             : #endif
     110             :     int         NamedLWLockTrancheRequests;
     111             :     NamedLWLockTranche *NamedLWLockTrancheArray;
     112             :     LWLockPadded *MainLWLockArray;
     113             :     slock_t    *ProcStructLock;
     114             :     PROC_HDR   *ProcGlobal;
     115             :     PGPROC     *AuxiliaryProcs;
     116             :     PGPROC     *PreparedXactProcs;
     117             :     PMSignalData *PMSignalState;
     118             :     pid_t       PostmasterPid;
     119             :     TimestampTz PgStartTime;
     120             :     TimestampTz PgReloadTime;
     121             :     pg_time_t   first_syslogger_file_time;
     122             :     bool        redirection_done;
     123             :     bool        IsBinaryUpgrade;
     124             :     bool        query_id_enabled;
     125             :     int         max_safe_fds;
     126             :     int         MaxBackends;
     127             : #ifdef WIN32
     128             :     HANDLE      PostmasterHandle;
     129             :     HANDLE      initial_signal_pipe;
     130             :     HANDLE      syslogPipe[2];
     131             : #else
     132             :     int         postmaster_alive_fds[2];
     133             :     int         syslogPipe[2];
     134             : #endif
     135             :     char        my_exec_path[MAXPGPATH];
     136             :     char        pkglib_path[MAXPGPATH];
     137             : 
     138             :     /*
     139             :      * These are only used by backend processes, but are here because passing
     140             :      * a socket needs some special handling on Windows. 'client_sock' is an
     141             :      * explicit argument to postmaster_child_launch, but is stored in
     142             :      * MyClientSocket in the child process.
     143             :      */
     144             :     ClientSocket client_sock;
     145             :     InheritableSocket inh_sock;
     146             : 
     147             :     /*
     148             :      * Extra startup data, content depends on the child process.
     149             :      */
     150             :     size_t      startup_data_len;
     151             :     char        startup_data[FLEXIBLE_ARRAY_MEMBER];
     152             : } BackendParameters;
     153             : 
     154             : #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
     155             : 
     156             : static void read_backend_variables(char *id, char **startup_data, size_t *startup_data_len);
     157             : static void restore_backend_variables(BackendParameters *param);
     158             : 
     159             : static bool save_backend_variables(BackendParameters *param, ClientSocket *client_sock,
     160             : #ifdef WIN32
     161             :                                    HANDLE childProcess, pid_t childPid,
     162             : #endif
     163             :                                    char *startup_data, size_t startup_data_len);
     164             : 
     165             : static pid_t internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock);
     166             : 
     167             : #endif                          /* EXEC_BACKEND */
     168             : 
     169             : /*
     170             :  * Information needed to launch different kinds of child processes.
     171             :  */
     172             : typedef struct
     173             : {
     174             :     const char *name;
     175             :     void        (*main_fn) (char *startup_data, size_t startup_data_len) pg_attribute_noreturn();
     176             :     bool        shmem_attach;
     177             : } child_process_kind;
     178             : 
     179             : child_process_kind child_process_kinds[] = {
     180             :     [B_INVALID] = {"invalid", NULL, false},
     181             : 
     182             :     [B_BACKEND] = {"backend", BackendMain, true},
     183             :     [B_AUTOVAC_LAUNCHER] = {"autovacuum launcher", AutoVacLauncherMain, true},
     184             :     [B_AUTOVAC_WORKER] = {"autovacuum worker", AutoVacWorkerMain, true},
     185             :     [B_BG_WORKER] = {"bgworker", BackgroundWorkerMain, true},
     186             : 
     187             :     /*
     188             :      * WAL senders start their life as regular backend processes, and change
     189             :      * their type after authenticating the client for replication.  We list it
     190             :      * here for PostmasterChildName() but cannot launch them directly.
     191             :      */
     192             :     [B_WAL_SENDER] = {"wal sender", NULL, true},
     193             :     [B_SLOTSYNC_WORKER] = {"slot sync worker", ReplSlotSyncWorkerMain, true},
     194             : 
     195             :     [B_STANDALONE_BACKEND] = {"standalone backend", NULL, false},
     196             : 
     197             :     [B_ARCHIVER] = {"archiver", PgArchiverMain, true},
     198             :     [B_BG_WRITER] = {"bgwriter", BackgroundWriterMain, true},
     199             :     [B_CHECKPOINTER] = {"checkpointer", CheckpointerMain, true},
     200             :     [B_STARTUP] = {"startup", StartupProcessMain, true},
     201             :     [B_WAL_RECEIVER] = {"wal_receiver", WalReceiverMain, true},
     202             :     [B_WAL_SUMMARIZER] = {"wal_summarizer", WalSummarizerMain, true},
     203             :     [B_WAL_WRITER] = {"wal_writer", WalWriterMain, true},
     204             : 
     205             :     [B_LOGGER] = {"syslogger", SysLoggerMain, false},
     206             : };
     207             : 
     208             : const char *
     209           0 : PostmasterChildName(BackendType child_type)
     210             : {
     211           0 :     return child_process_kinds[child_type].name;
     212             : }
     213             : 
     214             : /*
     215             :  * Start a new postmaster child process.
     216             :  *
     217             :  * The child process will be restored to roughly the same state whether
     218             :  * EXEC_BACKEND is used or not: it will be attached to shared memory, and fds
     219             :  * and other resources that we've inherited from postmaster that are not
     220             :  * needed in a child process have been closed.
     221             :  *
     222             :  * 'startup_data' is an optional contiguous chunk of data that is passed to
     223             :  * the child process.
     224             :  */
     225             : pid_t
     226       33194 : postmaster_child_launch(BackendType child_type,
     227             :                         char *startup_data, size_t startup_data_len,
     228             :                         ClientSocket *client_sock)
     229             : {
     230             :     pid_t       pid;
     231             : 
     232             :     Assert(IsPostmasterEnvironment && !IsUnderPostmaster);
     233             : 
     234             : #ifdef EXEC_BACKEND
     235             :     pid = internal_forkexec(child_process_kinds[child_type].name,
     236             :                             startup_data, startup_data_len, client_sock);
     237             :     /* the child process will arrive in SubPostmasterMain */
     238             : #else                           /* !EXEC_BACKEND */
     239       33194 :     pid = fork_process();
     240       63126 :     if (pid == 0)               /* child */
     241             :     {
     242             :         /* Close the postmaster's sockets */
     243       29938 :         ClosePostmasterPorts(child_type == B_LOGGER);
     244             : 
     245             :         /* Detangle from postmaster */
     246       29938 :         InitPostmasterChild();
     247             : 
     248             :         /*
     249             :          * Enter the Main function with TopMemoryContext.  The startup data is
     250             :          * allocated in PostmasterContext, so we cannot release it here yet.
     251             :          * The Main function will do it after it's done handling the startup
     252             :          * data.
     253             :          */
     254       29938 :         MemoryContextSwitchTo(TopMemoryContext);
     255             : 
     256       29938 :         if (client_sock)
     257             :         {
     258       21026 :             MyClientSocket = palloc(sizeof(ClientSocket));
     259       21026 :             memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
     260             :         }
     261             : 
     262             :         /*
     263             :          * Run the appropriate Main function
     264             :          */
     265       29938 :         child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     266             :         pg_unreachable();       /* main_fn never returns */
     267             :     }
     268             : #endif                          /* EXEC_BACKEND */
     269       33188 :     return pid;
     270             : }
     271             : 
     272             : #ifdef EXEC_BACKEND
     273             : #ifndef WIN32
     274             : 
     275             : /*
     276             :  * internal_forkexec non-win32 implementation
     277             :  *
     278             :  * - writes out backend variables to the parameter file
     279             :  * - fork():s, and then exec():s the child process
     280             :  */
     281             : static pid_t
     282             : internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock)
     283             : {
     284             :     static unsigned long tmpBackendFileNum = 0;
     285             :     pid_t       pid;
     286             :     char        tmpfilename[MAXPGPATH];
     287             :     size_t      paramsz;
     288             :     BackendParameters *param;
     289             :     FILE       *fp;
     290             :     char       *argv[4];
     291             :     char        forkav[MAXPGPATH];
     292             : 
     293             :     /*
     294             :      * Use palloc0 to make sure padding bytes are initialized, to prevent
     295             :      * Valgrind from complaining about writing uninitialized bytes to the
     296             :      * file.  This isn't performance critical, and the win32 implementation
     297             :      * initializes the padding bytes to zeros, so do it even when not using
     298             :      * Valgrind.
     299             :      */
     300             :     paramsz = SizeOfBackendParameters(startup_data_len);
     301             :     param = palloc0(paramsz);
     302             :     if (!save_backend_variables(param, client_sock, startup_data, startup_data_len))
     303             :     {
     304             :         pfree(param);
     305             :         return -1;              /* log made by save_backend_variables */
     306             :     }
     307             : 
     308             :     /* Calculate name for temp file */
     309             :     snprintf(tmpfilename, MAXPGPATH, "%s/%s.backend_var.%d.%lu",
     310             :              PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
     311             :              MyProcPid, ++tmpBackendFileNum);
     312             : 
     313             :     /* Open file */
     314             :     fp = AllocateFile(tmpfilename, PG_BINARY_W);
     315             :     if (!fp)
     316             :     {
     317             :         /*
     318             :          * As in OpenTemporaryFileInTablespace, try to make the temp-file
     319             :          * directory, ignoring errors.
     320             :          */
     321             :         (void) MakePGDirectory(PG_TEMP_FILES_DIR);
     322             : 
     323             :         fp = AllocateFile(tmpfilename, PG_BINARY_W);
     324             :         if (!fp)
     325             :         {
     326             :             ereport(LOG,
     327             :                     (errcode_for_file_access(),
     328             :                      errmsg("could not create file \"%s\": %m",
     329             :                             tmpfilename)));
     330             :             pfree(param);
     331             :             return -1;
     332             :         }
     333             :     }
     334             : 
     335             :     if (fwrite(param, paramsz, 1, fp) != 1)
     336             :     {
     337             :         ereport(LOG,
     338             :                 (errcode_for_file_access(),
     339             :                  errmsg("could not write to file \"%s\": %m", tmpfilename)));
     340             :         FreeFile(fp);
     341             :         pfree(param);
     342             :         return -1;
     343             :     }
     344             :     pfree(param);
     345             : 
     346             :     /* Release file */
     347             :     if (FreeFile(fp))
     348             :     {
     349             :         ereport(LOG,
     350             :                 (errcode_for_file_access(),
     351             :                  errmsg("could not write to file \"%s\": %m", tmpfilename)));
     352             :         return -1;
     353             :     }
     354             : 
     355             :     /* set up argv properly */
     356             :     argv[0] = "postgres";
     357             :     snprintf(forkav, MAXPGPATH, "--forkchild=%s", child_kind);
     358             :     argv[1] = forkav;
     359             :     /* Insert temp file name after --forkchild argument */
     360             :     argv[2] = tmpfilename;
     361             :     argv[3] = NULL;
     362             : 
     363             :     /* Fire off execv in child */
     364             :     if ((pid = fork_process()) == 0)
     365             :     {
     366             :         if (execv(postgres_exec_path, argv) < 0)
     367             :         {
     368             :             ereport(LOG,
     369             :                     (errmsg("could not execute server process \"%s\": %m",
     370             :                             postgres_exec_path)));
     371             :             /* We're already in the child process here, can't return */
     372             :             exit(1);
     373             :         }
     374             :     }
     375             : 
     376             :     return pid;                 /* Parent returns pid, or -1 on fork failure */
     377             : }
     378             : #else                           /* WIN32 */
     379             : 
     380             : /*
     381             :  * internal_forkexec win32 implementation
     382             :  *
     383             :  * - starts backend using CreateProcess(), in suspended state
     384             :  * - writes out backend variables to the parameter file
     385             :  *  - during this, duplicates handles and sockets required for
     386             :  *    inheritance into the new process
     387             :  * - resumes execution of the new process once the backend parameter
     388             :  *   file is complete.
     389             :  */
     390             : static pid_t
     391             : internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock)
     392             : {
     393             :     int         retry_count = 0;
     394             :     STARTUPINFO si;
     395             :     PROCESS_INFORMATION pi;
     396             :     char        cmdLine[MAXPGPATH * 2];
     397             :     HANDLE      paramHandle;
     398             :     BackendParameters *param;
     399             :     SECURITY_ATTRIBUTES sa;
     400             :     size_t      paramsz;
     401             :     char        paramHandleStr[32];
     402             :     int         l;
     403             : 
     404             :     paramsz = SizeOfBackendParameters(startup_data_len);
     405             : 
     406             :     /* Resume here if we need to retry */
     407             : retry:
     408             : 
     409             :     /* Set up shared memory for parameter passing */
     410             :     ZeroMemory(&sa, sizeof(sa));
     411             :     sa.nLength = sizeof(sa);
     412             :     sa.bInheritHandle = TRUE;
     413             :     paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
     414             :                                     &sa,
     415             :                                     PAGE_READWRITE,
     416             :                                     0,
     417             :                                     paramsz,
     418             :                                     NULL);
     419             :     if (paramHandle == INVALID_HANDLE_VALUE)
     420             :     {
     421             :         ereport(LOG,
     422             :                 (errmsg("could not create backend parameter file mapping: error code %lu",
     423             :                         GetLastError())));
     424             :         return -1;
     425             :     }
     426             :     param = MapViewOfFile(paramHandle, FILE_MAP_WRITE, 0, 0, paramsz);
     427             :     if (!param)
     428             :     {
     429             :         ereport(LOG,
     430             :                 (errmsg("could not map backend parameter memory: error code %lu",
     431             :                         GetLastError())));
     432             :         CloseHandle(paramHandle);
     433             :         return -1;
     434             :     }
     435             : 
     436             :     /* Format the cmd line */
     437             : #ifdef _WIN64
     438             :     sprintf(paramHandleStr, "%llu", (LONG_PTR) paramHandle);
     439             : #else
     440             :     sprintf(paramHandleStr, "%lu", (DWORD) paramHandle);
     441             : #endif
     442             :     l = snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\" --forkchild=\"%s\" %s",
     443             :                  postgres_exec_path, child_kind, paramHandleStr);
     444             :     if (l >= sizeof(cmdLine))
     445             :     {
     446             :         ereport(LOG,
     447             :                 (errmsg("subprocess command line too long")));
     448             :         UnmapViewOfFile(param);
     449             :         CloseHandle(paramHandle);
     450             :         return -1;
     451             :     }
     452             : 
     453             :     memset(&pi, 0, sizeof(pi));
     454             :     memset(&si, 0, sizeof(si));
     455             :     si.cb = sizeof(si);
     456             : 
     457             :     /*
     458             :      * Create the subprocess in a suspended state. This will be resumed later,
     459             :      * once we have written out the parameter file.
     460             :      */
     461             :     if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED,
     462             :                        NULL, NULL, &si, &pi))
     463             :     {
     464             :         ereport(LOG,
     465             :                 (errmsg("CreateProcess() call failed: %m (error code %lu)",
     466             :                         GetLastError())));
     467             :         UnmapViewOfFile(param);
     468             :         CloseHandle(paramHandle);
     469             :         return -1;
     470             :     }
     471             : 
     472             :     if (!save_backend_variables(param, client_sock, pi.hProcess, pi.dwProcessId, startup_data, startup_data_len))
     473             :     {
     474             :         /*
     475             :          * log made by save_backend_variables, but we have to clean up the
     476             :          * mess with the half-started process
     477             :          */
     478             :         if (!TerminateProcess(pi.hProcess, 255))
     479             :             ereport(LOG,
     480             :                     (errmsg_internal("could not terminate unstarted process: error code %lu",
     481             :                                      GetLastError())));
     482             :         CloseHandle(pi.hProcess);
     483             :         CloseHandle(pi.hThread);
     484             :         UnmapViewOfFile(param);
     485             :         CloseHandle(paramHandle);
     486             :         return -1;              /* log made by save_backend_variables */
     487             :     }
     488             : 
     489             :     /* Drop the parameter shared memory that is now inherited to the backend */
     490             :     if (!UnmapViewOfFile(param))
     491             :         ereport(LOG,
     492             :                 (errmsg("could not unmap view of backend parameter file: error code %lu",
     493             :                         GetLastError())));
     494             :     if (!CloseHandle(paramHandle))
     495             :         ereport(LOG,
     496             :                 (errmsg("could not close handle to backend parameter file: error code %lu",
     497             :                         GetLastError())));
     498             : 
     499             :     /*
     500             :      * Reserve the memory region used by our main shared memory segment before
     501             :      * we resume the child process.  Normally this should succeed, but if ASLR
     502             :      * is active then it might sometimes fail due to the stack or heap having
     503             :      * gotten mapped into that range.  In that case, just terminate the
     504             :      * process and retry.
     505             :      */
     506             :     if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
     507             :     {
     508             :         /* pgwin32_ReserveSharedMemoryRegion already made a log entry */
     509             :         if (!TerminateProcess(pi.hProcess, 255))
     510             :             ereport(LOG,
     511             :                     (errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
     512             :                                      GetLastError())));
     513             :         CloseHandle(pi.hProcess);
     514             :         CloseHandle(pi.hThread);
     515             :         if (++retry_count < 100)
     516             :             goto retry;
     517             :         ereport(LOG,
     518             :                 (errmsg("giving up after too many tries to reserve shared memory"),
     519             :                  errhint("This might be caused by ASLR or antivirus software.")));
     520             :         return -1;
     521             :     }
     522             : 
     523             :     /*
     524             :      * Now that the backend variables are written out, we start the child
     525             :      * thread so it can start initializing while we set up the rest of the
     526             :      * parent state.
     527             :      */
     528             :     if (ResumeThread(pi.hThread) == -1)
     529             :     {
     530             :         if (!TerminateProcess(pi.hProcess, 255))
     531             :         {
     532             :             ereport(LOG,
     533             :                     (errmsg_internal("could not terminate unstartable process: error code %lu",
     534             :                                      GetLastError())));
     535             :             CloseHandle(pi.hProcess);
     536             :             CloseHandle(pi.hThread);
     537             :             return -1;
     538             :         }
     539             :         CloseHandle(pi.hProcess);
     540             :         CloseHandle(pi.hThread);
     541             :         ereport(LOG,
     542             :                 (errmsg_internal("could not resume thread of unstarted process: error code %lu",
     543             :                                  GetLastError())));
     544             :         return -1;
     545             :     }
     546             : 
     547             :     /* Set up notification when the child process dies */
     548             :     pgwin32_register_deadchild_callback(pi.hProcess, pi.dwProcessId);
     549             : 
     550             :     /* Don't close pi.hProcess, it's owned by the deadchild callback now */
     551             : 
     552             :     CloseHandle(pi.hThread);
     553             : 
     554             :     return pi.dwProcessId;
     555             : }
     556             : #endif                          /* WIN32 */
     557             : 
     558             : /*
     559             :  * SubPostmasterMain -- Get the fork/exec'd process into a state equivalent
     560             :  *          to what it would be if we'd simply forked on Unix, and then
     561             :  *          dispatch to the appropriate place.
     562             :  *
     563             :  * The first two command line arguments are expected to be "--forkchild=<name>",
     564             :  * where <name> indicates which postmaster child we are to become, and
     565             :  * the name of a variables file that we can read to load data that would
     566             :  * have been inherited by fork() on Unix.
     567             :  */
     568             : void
     569             : SubPostmasterMain(int argc, char *argv[])
     570             : {
     571             :     char       *startup_data;
     572             :     size_t      startup_data_len;
     573             :     char       *child_kind;
     574             :     BackendType child_type;
     575             :     bool        found = false;
     576             : 
     577             :     /* In EXEC_BACKEND case we will not have inherited these settings */
     578             :     IsPostmasterEnvironment = true;
     579             :     whereToSendOutput = DestNone;
     580             : 
     581             :     /* Setup essential subsystems (to ensure elog() behaves sanely) */
     582             :     InitializeGUCOptions();
     583             : 
     584             :     /* Check we got appropriate args */
     585             :     if (argc != 3)
     586             :         elog(FATAL, "invalid subpostmaster invocation");
     587             : 
     588             :     /* Find the entry in child_process_kinds */
     589             :     if (strncmp(argv[1], "--forkchild=", 12) != 0)
     590             :         elog(FATAL, "invalid subpostmaster invocation (--forkchild argument missing)");
     591             :     child_kind = argv[1] + 12;
     592             :     found = false;
     593             :     for (int idx = 0; idx < lengthof(child_process_kinds); idx++)
     594             :     {
     595             :         if (strcmp(child_process_kinds[idx].name, child_kind) == 0)
     596             :         {
     597             :             child_type = (BackendType) idx;
     598             :             found = true;
     599             :             break;
     600             :         }
     601             :     }
     602             :     if (!found)
     603             :         elog(ERROR, "unknown child kind %s", child_kind);
     604             : 
     605             :     /* Read in the variables file */
     606             :     read_backend_variables(argv[2], &startup_data, &startup_data_len);
     607             : 
     608             :     /* Close the postmaster's sockets (as soon as we know them) */
     609             :     ClosePostmasterPorts(child_type == B_LOGGER);
     610             : 
     611             :     /* Setup as postmaster child */
     612             :     InitPostmasterChild();
     613             : 
     614             :     /*
     615             :      * If appropriate, physically re-attach to shared memory segment. We want
     616             :      * to do this before going any further to ensure that we can attach at the
     617             :      * same address the postmaster used.  On the other hand, if we choose not
     618             :      * to re-attach, we may have other cleanup to do.
     619             :      *
     620             :      * If testing EXEC_BACKEND on Linux, you should run this as root before
     621             :      * starting the postmaster:
     622             :      *
     623             :      * sysctl -w kernel.randomize_va_space=0
     624             :      *
     625             :      * This prevents using randomized stack and code addresses that cause the
     626             :      * child process's memory map to be different from the parent's, making it
     627             :      * sometimes impossible to attach to shared memory at the desired address.
     628             :      * Return the setting to its old value (usually '1' or '2') when finished.
     629             :      */
     630             :     if (child_process_kinds[child_type].shmem_attach)
     631             :         PGSharedMemoryReAttach();
     632             :     else
     633             :         PGSharedMemoryNoReAttach();
     634             : 
     635             :     /* Read in remaining GUC variables */
     636             :     read_nondefault_variables();
     637             : 
     638             :     /*
     639             :      * Check that the data directory looks valid, which will also check the
     640             :      * privileges on the data directory and update our umask and file/group
     641             :      * variables for creating files later.  Note: this should really be done
     642             :      * before we create any files or directories.
     643             :      */
     644             :     checkDataDir();
     645             : 
     646             :     /*
     647             :      * (re-)read control file, as it contains config. The postmaster will
     648             :      * already have read this, but this process doesn't know about that.
     649             :      */
     650             :     LocalProcessControlFile(false);
     651             : 
     652             :     /*
     653             :      * Reload any libraries that were preloaded by the postmaster.  Since we
     654             :      * exec'd this process, those libraries didn't come along with us; but we
     655             :      * should load them into all child processes to be consistent with the
     656             :      * non-EXEC_BACKEND behavior.
     657             :      */
     658             :     process_shared_preload_libraries();
     659             : 
     660             :     /* Restore basic shared memory pointers */
     661             :     if (UsedShmemSegAddr != NULL)
     662             :         InitShmemAccess(UsedShmemSegAddr);
     663             : 
     664             :     /*
     665             :      * Run the appropriate Main function
     666             :      */
     667             :     child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     668             :     pg_unreachable();           /* main_fn never returns */
     669             : }
     670             : 
     671             : /*
     672             :  * The following need to be available to the save/restore_backend_variables
     673             :  * functions.  They are marked NON_EXEC_STATIC in their home modules.
     674             :  */
     675             : extern slock_t *ShmemLock;
     676             : extern slock_t *ProcStructLock;
     677             : extern PGPROC *AuxiliaryProcs;
     678             : extern PMSignalData *PMSignalState;
     679             : extern pg_time_t first_syslogger_file_time;
     680             : extern struct bkend *ShmemBackendArray;
     681             : extern bool redirection_done;
     682             : 
     683             : #ifndef WIN32
     684             : #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
     685             : #define read_inheritable_socket(dest, src) (*(dest) = *(src))
     686             : #else
     687             : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
     688             : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
     689             :                                      pid_t childPid);
     690             : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
     691             : #endif
     692             : 
     693             : 
     694             : /* Save critical backend variables into the BackendParameters struct */
     695             : static bool
     696             : save_backend_variables(BackendParameters *param, ClientSocket *client_sock,
     697             : #ifdef WIN32
     698             :                        HANDLE childProcess, pid_t childPid,
     699             : #endif
     700             :                        char *startup_data, size_t startup_data_len)
     701             : {
     702             :     if (client_sock)
     703             :         memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
     704             :     else
     705             :         memset(&param->client_sock, 0, sizeof(ClientSocket));
     706             :     if (!write_inheritable_socket(&param->inh_sock,
     707             :                                   client_sock ? client_sock->sock : PGINVALID_SOCKET,
     708             :                                   childPid))
     709             :         return false;
     710             : 
     711             :     strlcpy(param->DataDir, DataDir, MAXPGPATH);
     712             : 
     713             :     param->MyCancelKey = MyCancelKey;
     714             :     param->MyPMChildSlot = MyPMChildSlot;
     715             : 
     716             : #ifdef WIN32
     717             :     param->ShmemProtectiveRegion = ShmemProtectiveRegion;
     718             : #endif
     719             :     param->UsedShmemSegID = UsedShmemSegID;
     720             :     param->UsedShmemSegAddr = UsedShmemSegAddr;
     721             : 
     722             :     param->ShmemLock = ShmemLock;
     723             :     param->ShmemBackendArray = ShmemBackendArray;
     724             : 
     725             : #ifndef HAVE_SPINLOCKS
     726             :     param->SpinlockSemaArray = SpinlockSemaArray;
     727             : #endif
     728             :     param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
     729             :     param->NamedLWLockTrancheArray = NamedLWLockTrancheArray;
     730             :     param->MainLWLockArray = MainLWLockArray;
     731             :     param->ProcStructLock = ProcStructLock;
     732             :     param->ProcGlobal = ProcGlobal;
     733             :     param->AuxiliaryProcs = AuxiliaryProcs;
     734             :     param->PreparedXactProcs = PreparedXactProcs;
     735             :     param->PMSignalState = PMSignalState;
     736             : 
     737             :     param->PostmasterPid = PostmasterPid;
     738             :     param->PgStartTime = PgStartTime;
     739             :     param->PgReloadTime = PgReloadTime;
     740             :     param->first_syslogger_file_time = first_syslogger_file_time;
     741             : 
     742             :     param->redirection_done = redirection_done;
     743             :     param->IsBinaryUpgrade = IsBinaryUpgrade;
     744             :     param->query_id_enabled = query_id_enabled;
     745             :     param->max_safe_fds = max_safe_fds;
     746             : 
     747             :     param->MaxBackends = MaxBackends;
     748             : 
     749             : #ifdef WIN32
     750             :     param->PostmasterHandle = PostmasterHandle;
     751             :     if (!write_duplicated_handle(&param->initial_signal_pipe,
     752             :                                  pgwin32_create_signal_listener(childPid),
     753             :                                  childProcess))
     754             :         return false;
     755             : #else
     756             :     memcpy(&param->postmaster_alive_fds, &postmaster_alive_fds,
     757             :            sizeof(postmaster_alive_fds));
     758             : #endif
     759             : 
     760             :     memcpy(&param->syslogPipe, &syslogPipe, sizeof(syslogPipe));
     761             : 
     762             :     strlcpy(param->my_exec_path, my_exec_path, MAXPGPATH);
     763             : 
     764             :     strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
     765             : 
     766             :     param->startup_data_len = startup_data_len;
     767             :     memcpy(param->startup_data, startup_data, startup_data_len);
     768             : 
     769             :     return true;
     770             : }
     771             : 
     772             : #ifdef WIN32
     773             : /*
     774             :  * Duplicate a handle for usage in a child process, and write the child
     775             :  * process instance of the handle to the parameter file.
     776             :  */
     777             : static bool
     778             : write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
     779             : {
     780             :     HANDLE      hChild = INVALID_HANDLE_VALUE;
     781             : 
     782             :     if (!DuplicateHandle(GetCurrentProcess(),
     783             :                          src,
     784             :                          childProcess,
     785             :                          &hChild,
     786             :                          0,
     787             :                          TRUE,
     788             :                          DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
     789             :     {
     790             :         ereport(LOG,
     791             :                 (errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %lu",
     792             :                                  GetLastError())));
     793             :         return false;
     794             :     }
     795             : 
     796             :     *dest = hChild;
     797             :     return true;
     798             : }
     799             : 
     800             : /*
     801             :  * Duplicate a socket for usage in a child process, and write the resulting
     802             :  * structure to the parameter file.
     803             :  * This is required because a number of LSPs (Layered Service Providers) very
     804             :  * common on Windows (antivirus, firewalls, download managers etc) break
     805             :  * straight socket inheritance.
     806             :  */
     807             : static bool
     808             : write_inheritable_socket(InheritableSocket *dest, SOCKET src, pid_t childpid)
     809             : {
     810             :     dest->origsocket = src;
     811             :     if (src != 0 && src != PGINVALID_SOCKET)
     812             :     {
     813             :         /* Actual socket */
     814             :         if (WSADuplicateSocket(src, childpid, &dest->wsainfo) != 0)
     815             :         {
     816             :             ereport(LOG,
     817             :                     (errmsg("could not duplicate socket %d for use in backend: error code %d",
     818             :                             (int) src, WSAGetLastError())));
     819             :             return false;
     820             :         }
     821             :     }
     822             :     return true;
     823             : }
     824             : 
     825             : /*
     826             :  * Read a duplicate socket structure back, and get the socket descriptor.
     827             :  */
     828             : static void
     829             : read_inheritable_socket(SOCKET *dest, InheritableSocket *src)
     830             : {
     831             :     SOCKET      s;
     832             : 
     833             :     if (src->origsocket == PGINVALID_SOCKET || src->origsocket == 0)
     834             :     {
     835             :         /* Not a real socket! */
     836             :         *dest = src->origsocket;
     837             :     }
     838             :     else
     839             :     {
     840             :         /* Actual socket, so create from structure */
     841             :         s = WSASocket(FROM_PROTOCOL_INFO,
     842             :                       FROM_PROTOCOL_INFO,
     843             :                       FROM_PROTOCOL_INFO,
     844             :                       &src->wsainfo,
     845             :                       0,
     846             :                       0);
     847             :         if (s == INVALID_SOCKET)
     848             :         {
     849             :             write_stderr("could not create inherited socket: error code %d\n",
     850             :                          WSAGetLastError());
     851             :             exit(1);
     852             :         }
     853             :         *dest = s;
     854             : 
     855             :         /*
     856             :          * To make sure we don't get two references to the same socket, close
     857             :          * the original one. (This would happen when inheritance actually
     858             :          * works..
     859             :          */
     860             :         closesocket(src->origsocket);
     861             :     }
     862             : }
     863             : #endif
     864             : 
     865             : static void
     866             : read_backend_variables(char *id, char **startup_data, size_t *startup_data_len)
     867             : {
     868             :     BackendParameters param;
     869             : 
     870             : #ifndef WIN32
     871             :     /* Non-win32 implementation reads from file */
     872             :     FILE       *fp;
     873             : 
     874             :     /* Open file */
     875             :     fp = AllocateFile(id, PG_BINARY_R);
     876             :     if (!fp)
     877             :     {
     878             :         write_stderr("could not open backend variables file \"%s\": %m\n", id);
     879             :         exit(1);
     880             :     }
     881             : 
     882             :     if (fread(&param, sizeof(param), 1, fp) != 1)
     883             :     {
     884             :         write_stderr("could not read from backend variables file \"%s\": %m\n", id);
     885             :         exit(1);
     886             :     }
     887             : 
     888             :     /* read startup data */
     889             :     *startup_data_len = param.startup_data_len;
     890             :     if (param.startup_data_len > 0)
     891             :     {
     892             :         *startup_data = palloc(*startup_data_len);
     893             :         if (fread(*startup_data, *startup_data_len, 1, fp) != 1)
     894             :         {
     895             :             write_stderr("could not read startup data from backend variables file \"%s\": %m\n",
     896             :                          id);
     897             :             exit(1);
     898             :         }
     899             :     }
     900             :     else
     901             :         *startup_data = NULL;
     902             : 
     903             :     /* Release file */
     904             :     FreeFile(fp);
     905             :     if (unlink(id) != 0)
     906             :     {
     907             :         write_stderr("could not remove file \"%s\": %m\n", id);
     908             :         exit(1);
     909             :     }
     910             : #else
     911             :     /* Win32 version uses mapped file */
     912             :     HANDLE      paramHandle;
     913             :     BackendParameters *paramp;
     914             : 
     915             : #ifdef _WIN64
     916             :     paramHandle = (HANDLE) _atoi64(id);
     917             : #else
     918             :     paramHandle = (HANDLE) atol(id);
     919             : #endif
     920             :     paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
     921             :     if (!paramp)
     922             :     {
     923             :         write_stderr("could not map view of backend variables: error code %lu\n",
     924             :                      GetLastError());
     925             :         exit(1);
     926             :     }
     927             : 
     928             :     memcpy(&param, paramp, sizeof(BackendParameters));
     929             : 
     930             :     /* read startup data */
     931             :     *startup_data_len = param.startup_data_len;
     932             :     if (param.startup_data_len > 0)
     933             :     {
     934             :         *startup_data = palloc(paramp->startup_data_len);
     935             :         memcpy(*startup_data, paramp->startup_data, param.startup_data_len);
     936             :     }
     937             :     else
     938             :         *startup_data = NULL;
     939             : 
     940             :     if (!UnmapViewOfFile(paramp))
     941             :     {
     942             :         write_stderr("could not unmap view of backend variables: error code %lu\n",
     943             :                      GetLastError());
     944             :         exit(1);
     945             :     }
     946             : 
     947             :     if (!CloseHandle(paramHandle))
     948             :     {
     949             :         write_stderr("could not close handle to backend parameter variables: error code %lu\n",
     950             :                      GetLastError());
     951             :         exit(1);
     952             :     }
     953             : #endif
     954             : 
     955             :     restore_backend_variables(&param);
     956             : }
     957             : 
     958             : /* Restore critical backend variables from the BackendParameters struct */
     959             : static void
     960             : restore_backend_variables(BackendParameters *param)
     961             : {
     962             :     if (param->client_sock.sock != PGINVALID_SOCKET)
     963             :     {
     964             :         MyClientSocket = MemoryContextAlloc(TopMemoryContext, sizeof(ClientSocket));
     965             :         memcpy(MyClientSocket, &param->client_sock, sizeof(ClientSocket));
     966             :         read_inheritable_socket(&MyClientSocket->sock, &param->inh_sock);
     967             :     }
     968             : 
     969             :     SetDataDir(param->DataDir);
     970             : 
     971             :     MyCancelKey = param->MyCancelKey;
     972             :     MyPMChildSlot = param->MyPMChildSlot;
     973             : 
     974             : #ifdef WIN32
     975             :     ShmemProtectiveRegion = param->ShmemProtectiveRegion;
     976             : #endif
     977             :     UsedShmemSegID = param->UsedShmemSegID;
     978             :     UsedShmemSegAddr = param->UsedShmemSegAddr;
     979             : 
     980             :     ShmemLock = param->ShmemLock;
     981             :     ShmemBackendArray = param->ShmemBackendArray;
     982             : 
     983             : #ifndef HAVE_SPINLOCKS
     984             :     SpinlockSemaArray = param->SpinlockSemaArray;
     985             : #endif
     986             :     NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
     987             :     NamedLWLockTrancheArray = param->NamedLWLockTrancheArray;
     988             :     MainLWLockArray = param->MainLWLockArray;
     989             :     ProcStructLock = param->ProcStructLock;
     990             :     ProcGlobal = param->ProcGlobal;
     991             :     AuxiliaryProcs = param->AuxiliaryProcs;
     992             :     PreparedXactProcs = param->PreparedXactProcs;
     993             :     PMSignalState = param->PMSignalState;
     994             : 
     995             :     PostmasterPid = param->PostmasterPid;
     996             :     PgStartTime = param->PgStartTime;
     997             :     PgReloadTime = param->PgReloadTime;
     998             :     first_syslogger_file_time = param->first_syslogger_file_time;
     999             : 
    1000             :     redirection_done = param->redirection_done;
    1001             :     IsBinaryUpgrade = param->IsBinaryUpgrade;
    1002             :     query_id_enabled = param->query_id_enabled;
    1003             :     max_safe_fds = param->max_safe_fds;
    1004             : 
    1005             :     MaxBackends = param->MaxBackends;
    1006             : 
    1007             : #ifdef WIN32
    1008             :     PostmasterHandle = param->PostmasterHandle;
    1009             :     pgwin32_initial_signal_pipe = param->initial_signal_pipe;
    1010             : #else
    1011             :     memcpy(&postmaster_alive_fds, &param->postmaster_alive_fds,
    1012             :            sizeof(postmaster_alive_fds));
    1013             : #endif
    1014             : 
    1015             :     memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
    1016             : 
    1017             :     strlcpy(my_exec_path, param->my_exec_path, MAXPGPATH);
    1018             : 
    1019             :     strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
    1020             : 
    1021             :     /*
    1022             :      * We need to restore fd.c's counts of externally-opened FDs; to avoid
    1023             :      * confusion, be sure to do this after restoring max_safe_fds.  (Note:
    1024             :      * BackendInitialize will handle this for (*client_sock)->sock.)
    1025             :      */
    1026             : #ifndef WIN32
    1027             :     if (postmaster_alive_fds[0] >= 0)
    1028             :         ReserveExternalFD();
    1029             :     if (postmaster_alive_fds[1] >= 0)
    1030             :         ReserveExternalFD();
    1031             : #endif
    1032             : }
    1033             : 
    1034             : #endif                          /* EXEC_BACKEND */

Generated by: LCOV version 1.14